home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-09-28 | 196.9 KB | 5,337 lines |
-
- +-----------------------------------------------+
- | |
- | Amiga E v3.0a |
- | Compilateur du Langage E |
- | Par Wouter van Oortmerssen |
- | |
- | Traduction : Olivier ANH |
- | Membre du BUGSS |
- | Copyright 1994 BUGSS |
- | |
- +-----------------------------------------------+
-
- Contenu :
-
- 0. compilateur et introduction
- A. introduction
- B. la distribution
- C. restrictions de la version démo et registration
- D. utiliser lecompilateur
- E. changement de la v2.1b à la v3.0a
- F. information additionnelle
-
- 1. format
- A. tabulations, saut de ligne (lf) etc.
- B. commentaires
- C. identificateurs et types
-
- 2. valeurs immédiates
- A. décimales (1)
- B. héxadecimales ($1)
- C. binaires (%1)
- D. flottants (1.0)
- E. caractères ("a")
- F. chaines ('bla')
- G. listes ([1,2,3]) et listes typées
-
- 3. expressions
- A. format
- B. priorité des opérateurs
- C. types d'expressions
- D. appels de fonction
-
- 4. operateurs
- A. mathématiques (+ - * /)
- B. de comparaison (= <> > < >= <=)
- C. logiques (AND OR)
- D. unaire (SIZEOF ` ^ {} ++ -- -)
- E. triple (IF THEN ELSE)
- F. de structure (.)
- G. de tableau ([])
- H. flottants (|)
- I. expressions d'assignement (:=)
- J. séquence (BUT)
-
- 5. déclaration
- A. format (;)
- B. labels et gotos (JUMP)
- C. assignement (:=)
- D. mnémoniques assembleur
- E. conditionel (IF)
- F. for (FOR)
- G. while (WHILE)
- H. repeat (REPEAT)
- I. loop (LOOP)
- J. select-case (SELECT)
- K. incrémentation (INC/DEC)
- L. expressions vides (VOID)
-
- 6. fonction : définitions et déclarations
- A. définition et arguments des procédures (PROC)
- B. définitions locales et globales (DEF)
- C. endproc/return
- D. la fonction "main"
- E. variables système prédéfinies (built-in)
-
- 7. déclaration de constantes
- A. constantes (CONST)
- B. énumerations (ENUM)
- C. sets (SET)
- D. constantes prédéfinies (built-in)
-
- 8. types
- A. à propos du système "type"
- B. letype de base (LONG/PTR)
- C. le type simple (CHAR/INT/LONG)
- D. le type tableau (ARRAY)
- E. le type complexe (STRING/LIST)
- F. le type composé (OBJECT)
- G. initialisation
- H. l'essentiel du système de type du E
-
- 9. fonctions prédéfinies (built-in)
- A. fonctions d'entrées-sorties (I/O)
- B. chaines et fonctions de chaine
- C. listes et fonctions de liste
- D. fonctions de support Intuition
- E. fonctions de support graphique
- F. fonctions de support système
- G. fonctions mathémathiques et autres fonctions
- H. chaine et fonctions de lien entre listes
- I. Cellule Lisp et fonctions cellulaires
-
- 10. fonctions de bibliothèques (libraries) et modules
- A. appels de bibliothèques prédéfinies (built-in)
- B. interfacer le système amiga avec les modules v39
- C. compiler ses propres modules
- D. le module cache
-
- 11. expressions cotées (`)
- A. les cotes simple et l'analyse
- B. Eval()
- C. fonctions prédéfinies (built-in)
-
- 12. support des nombres flottants
- A. utilisation des flottants et fonctions d'opérateurs flottants
- B. expressions flottantes et conversions
-
- 13. gestion des exceptions
- A. définition des gestionnaires d'exceptions (HANDLE/EXCEPT)
- B. utilisation de la fonction Raise()
- C. définition des exceptions pour les fonctions prédéfinies (RAISE/IF)
- D. utilisation des identificateurs d'exception
-
- 14. programmation orientée objet (OO)
- A. Caractèristiques de l'OO en E
- B. héritage des objets
- C. chacher les données (EXPORT/PRIVATE/PUBLIC)
- D. méthodes and méthodes virtuelles
-
- 15. assembleur en ligne
- A. les identificateurs
- B. l'assembleur en ligne comparé au macro assembleur
- C. comment utiliser les données binaires (INCBIN/CHAR..)
- D. OPT ASM
- E. assembleur en ligne et variables registres
-
- 16. implémentations
- A. le mot-clé OPT
- B. le modèle small/large
- C. l'organisation de la pile
- D. les limites du code
- E. les messages d'érreurs, d'avertissements et de non-référence
- F. l'organisation des tampons du compilateur et allocation
- G. allocation des registres
-
- 17. utilitaires essentiels du E
- A. ShowModule
- B. ShowHunk
- C. Pragma2Module / Iconvert
- D. ShowCache / FlushCache
- E. ecompile.rexx
- F. o2m
- G. E-Yacc
- H. SrcGen
- I. EBuild
-
- 18. Appendices
- A. la grammaire du E
- B. tutorial
- C. comparaison du E avec C/C++/Pascal/Ada/Lisp etc.
-
-
-
- +-----------------------------------------------------------------------+
- | 0. COMPILATEUR ET INTRODUCTION |
- +-----------------------------------------------------------------------+
-
-
- 0A. introduction
- ----------------
-
- Le E est un langage de programmation hautement procédural, très influencé par
- les langages comme le C et le Modula2. C'est une langage tous azimuts, et
- l'implémentation sur l'Amiga est spécifiquement dirigé à la programmation
- d'applications systèmes.Points négatifs :
-
- C'est ce à quoi ressemble 'Hello World' en E :
-
- /* nominé pour l'Exemple Le Plus Ennuyant */
-
- PROC main()
- WriteF('Hello, World!\n')
- ENDPROC
-
-
- 0B. la distribution
- -------------------
-
- La distribution inclue:
-
- bin/ contient le compilateur EC et les utilitaires supports,
- modules/ Répertoire contenant tous les modules v39 ainsi des outils
- utiles à lier comme modules,
- docs/ documentation sur le E,
- src/ sources exemples en E.
-
- Cett distribution de l'Amiga E v3.0 incluant la version de démonstration du
- compilateur est Freeware, et peut être librement copié. Le compilateur que
- certains d'entre vous aurons reçut avec cette archive, n'est cependant pas
- freeware, et ne doit pas être copié pour d'autres personnes sinon vous-même.
-
- Distribuer des copies du E pour plus que le prix du disque et des frais
- d'envoie (en général <US$3), ou tout autre moyen de distribution avec la
- moindre intention de faire du profit, n'est pas autorisée.
-
- Cette distribution doit toujours être distribuée en un seul morceau, ie dans sa
- forme d'archive .lha originale. Aucune addition, modifications, distribution
- partielle ou quoi que soit d'autre n'est permis sans ma permission.
-
- Aucune garantie n'est donnée. Si vous utilisez le E pour noyer votre poisson
- rouge, ou bien le E ne vous convient pas pour commander des pizzas, c'est votre
- problême. Si quoi que se soit se passe, ne m'en blamez pas.
-
- Fred Fish a un permission spéciale pour distribuer le E sur son CD-ROM.
-
-
- 0C. restrictions de la démo et enregistrement
- ---------------------------------------------
-
- La distribution de l'Amiga E est Domaine Public, et contient la version de
- démonstration du compilateur. Les programmeurs enregistrés obtienne le
- compilateur entier dans une archive séparée, avec seulement "EC" dedans.
-
- Si vous avez déja reçut un EC enregistré, vous devez le mettre dans le
- répertoire Bin. L'archive de distribution peut être copiée librement (voir 0B
- là dessus), mais faites attention de ne pas distribuer votre version
- enregistrée de EC, même pas à des amis. Je n'ai pas fait de série (comme des
- numéros d'enregistrement) pour ces copies, car j'ai confiance en mes
- utilisateurs enregistrés, s'il vous plait, ne la cassez pas. L'enregistrement
- est abordable, et la v2.1b est toujours éxistante. Il n'y a donc plus aucune
- excuse pour pirater le E.
-
- Donc, qu'inclue la démo de ce compilateur ?
-
- Le compilateur ne vous recrachera que des éxécutables infèrieur à 12Ko,
- au delà, il affichera un "workspace full" (espace de travail plein). Sinon
- tout fonctionne.
-
- Vous avez 2 semaines pour évaluer cette démo, après celà vous décidez soit
- de vous enregistrer, soit de ne plus utiliser la version démo.
-
- Mis à jour :
-
- Les mises à jours pourront être trouvé dans le domaine public, et le mises
- à jours pour les EC enregistrés seront distribués sous forme de patches,
- aussi dans le domaine public
-
- Commander une copie :
-
- Le prix de base est de $40 US.
- Enlevez $5 US si vous voulez revecoir le version enregistrée de EC par
- Email (uuencodé) au lieu de disquette. Celà demande une connection
- _accessible_ aux Email. C'est le moyen le plus rapide de recevoir la v3.0.
-
- J'accepte les paiements dans d'autres monnaies, pour simplifier les choses
- à certaines personnes. Pas de monnaies rare s'il vous plait.
-
- Exemples (US$): 40
-
- Dutch Guilders (de préférence) 65
- Pound Sterling anglaise 26
- DeutchMark allemand 60
- Franc français 210
- Lire italienne 63000
-
- NOTE : ces prix ont été calculés au taux de change du 30 juin 1994, si
- votre monnaie s'envole, à vous d'ajuster. Avoir 1$ US au dessus du prix
- en Guilder n'est pas mal.
-
- M'envoyer de l'argent :
-
- Ce n'est pas simple. La plupart des banques rajoutent pas mal pour faire
- des tranfers d'argent. Voici quelques alternatives :
-
- - Envoyer de l'argent liquide (de préférence). Cela semble bizarre, mais
- c'est le meilleur moyen de faire passer de l'argent. Essayez de changer
- votre montant en Dutch-Guilder. Si vous n'êtes pas sûr de l'envoie, la
- plupart des bureux de postes offrent un service qui vous dira que la
- lettre est bien arrivée chez moi (lettre avec accusé de reception en
- France).
- - Transférer directement à mon compte bancaire :
- 427875951, ABN-AMRO bank, the netherlands (Pays Bas)
- ou mon compte postal :
- 6030387, PostBank, the netherlands (Pays Bas)
- assurez vous que vous couvrez aussi les coûts de transfer que la banque
- vous chargera.
- - En Europe, envoyez un EuroCheque (en Guilder). Je crois que ça ne coûte
- rien, mais vérifiez toujours.
- - Vous pouvez choisir d'autres méthodes, mais d'une manière générale,
- réalisez que c'est à vous de vous assurer que je pourrai _facilement_
- encaisser l'argent.
- - N'envoyez pas de CHEQUES. Les chèques (autres que les EuroChèques)
- demandent ici $15 US pour le transfer (si je peut tous les encaisser).
-
- Assurez vous de m'envoyer le plus d'informations possible, ie adresse
- complète, adresse Email, peut-être votre configuration Amiga etc. Je ne
- vais pas vous donner un stupide formulaire d'enregistrement à remplir :-)
-
- Mon adresse: (voir 0F)
-
-
- 0D. utiliser le compilateur
- ---------------------------
-
- Pour installer l'Amiga E sur votre système, copiez simplement toute la
- distribution où vous le désirez sur votre système. Extendez votre chemin
- (path) au répertoire BIN, assignez EMODULES: au directory MODULES.
-
- Syntaxe du compilateur (2.04+):
-
- SOURCE/A,REG=NUMREGALLOC/N/K,LARGE/S,SYM=SYMBOLHUNK/S,
- NOWARN/S,QUIET/S,ASM/S,ERRLINE/S,ERRBYTE/S,SHOWBUF/S,
- ADDBUF/N/K,IGNORECACHE/S,HOLD/S,WB/S,LINEDEBUG/S,OPTI/S:
-
- Pour 1.2 to 2.03:
-
- EC [-opts] <sourcefile>
-
- Comme exemple, on compile le programme 'HelloWorld.e'. Le compilateur va
- produire un éxécutable 'HelloWorld'.
-
- 1> ec helloworld
- Amiga E Compiler/Assembler/Linker v2.4f (c) 91/92/93 $#%!
- lexical analysing...
- parsing and compiling
- no error.
- 1> helloworld
- Hello, World!
- 1> list
- HelloWorld.e 89 ----rwed Oggi 17:37:00
- helloworld 656 ----rwed Oggi 17:37:00
- 2 files - 4 blocks used
-
- Note : le compilateur ne peut pas être mis résident
-
- Dernière note sur la compilation des exemples : si un programme utilise des
- modules pour des définitions de bibliothèques comme :
-
- MODULE 'GadTools', 'Reqtools'
-
- le compilateur a besoin de savoir où ils se trouvent. 2 solutions sont
- possibles :
- 1. vous faites l'assignement 'emodules:' vers le répertoire de modules
- (le mieux)
- 2. vous spécifiez dans le code source, où chercher les modules, comme :
- OPT DIR='dh0:src/e/modules'
-
- Options du compilateur :
-
- Ce sont des options standards à l'AligaDos. Vous pouvez les voir à tout
- moment en tapant 'EC ?'. Pour les options sous 1.2/1.3, les vieux arguments
- à la UNIX sont utilisés (doivent être écrit ensemble, et précédés d'un "-":
-
- LARGE -l compile avec le GRAND (LARGE) code/donnée. Voir 16A, OPT LARGE
- ASM -a met EC en mode assembleur. Voir 15D, OPT ASM
- NOWARN -n supprime les avertissements. Voir 16A, OPT NOWARN
- SYM -s ajoute un symbolhunk à l'éxécutable, en utilisation avec
- des Profilers, Debuggers, etc.
- REG N -r N utilise N registres par PROCédure pour l'allocation
- (0 par défaut, regarder autrepart comment on l'utilise!)
- QUIET -q si il n'y a aucune erreur ou alerte, EC n'affichera rien
- WB -w place le wb en avant (pour les scripts)
- SHOWBUF -b montre les informations sur la memoire
- ADDBUF -mX force EC d'allouer plus de memoire pour ses tampons (buffers).
- X compris entre 1 et 9, le nombre minimum de bloc de 100k
- à allouer. Par défaut : 1 (jamais utilisé)
- ERRLINE -e retourne le numéro de ligne où s'est produite l'erreur
- ERRBYTE -E retour l'offset de l'octet dans le fichier où s'est
- produite l'erreur
- IGNORECACHE -c n'utilise jamais le module cache
- HOLD -h attend un <return> dans la ligne de commande avant de
- quitter EC
- OPTI autorise toutes les optimisations (actuellement égale
- REG=5)
-
- Exemple : ec large blabla
- compile blabla.e avec le modèle large.
- Note : dans la plus part des cas, vous n'aurez pas a utiliser ces options.
-
-
- 0E. Les changements de v2.1b à v3.0a
- ------------------------------------
-
- Quoi de neuf dans la v3.0a:
- [divisé en 4 sections. Reportez vous à ce chapitre pour leur description]
-
- 1. Les grandes nouvelles caractèristiques :
-
- - compilation en modules [!] (voir 10C)
- - oo: héritage d'objets, privé/public, méthodes etc. (voir 14A)
- - arguments par défaut pour les PROCs (voir 6F) (et quelques builtins, aussi).
- - valeurs de retour multiple (voir 6G)
- - variables / allocation de registre (voir 16G, 15E, ...).
- - les réels (REALs) intégrés (voir 12)
- - opérateur NEW (voir 4K), et END (voir 5M) (avec une gestion super rapide de
- la mémoire)
- - une variation syntaxique puissante de SELECT (voir 5J)
- - unification (voir 4L)
- - permet des types plus complexes dans les OBJECTs, PTR TO <type> etc.
- (voir 8F) ensemble avec des réferences plus puissantes (voir 4F, x.y[a].z
- etc.)
- - garbage collected Lisp-Cells (voir 9I)
- - valeurs de fonction (appel de pointeur de PROCs) (voir 6H)
- - module caching (voir 17D, showcache)
- - reconstruction d'erreur: montre exactement l'endroit de l'erreur sur la
- ligne
- - un tas de nouvelles fonctions intégrés (voir 9A,...)
- - un tas de modules utiles (qui auront du poids bientôt)
- - des optimisations variées du compilateur qui accélère signicativement EC
- - plusieurs optimisations du code
- - système intelligent linker / module (voir 10C, entre autres)
- - le compilateur utilise beaucoup moins de mémoire
- - hunks symboliques et débbugage en ligne (voir 0D plus haut).
- - utilitaires variéss, tel que EE (L'éditeur E de Barry Wills),
- Build (un 'make'), o2m (convertis les fichiers asm .o files en modules),
- E-Yacc etc.
- - nouvelles docs, GRAND tutorial de Jason Hulance (plus connu sous 'Le Guide').
-
- 2. Les caractèristiques secondaires.
-
- - opérateur pointeur "::" (voir 4M)
- - EXCEPT DO: continue au handler (voir 13C)
- - EXIT <boolexp> dans WHILE/FOR (voir 5F)
- - commentaire sur une seule ligne (voir 1B)
- - pour quelques uns: les modules v39
- - les constantes caractères peuvent avoir "\n\t\e\a" "\0\\\b\q" maintenant.
- (\q = ")
- - warning for flakey "assignments" now with linenum.
- - définir un PTR TO <object> avec juste des [] donne un pointeur maintenant
- (par exemple x[1] = objet suivant)
- - un variété de petites optimisations de code
- - un tas de fonctions chaine/liste/entrée-sortie retourne maintenant des
- valeurs de retour utiles (voir 9A,...)
- - la ligne de commandes de EC est du style ReadArgs() pour les utilisateurs
- 2.04+ (voir 0D).
- - meilleur fins de ligne (voir 5A)
- - quelques nouveaux fonctions prédéfinies (voir 9A,...)
-
- 3. ERREURS (BUGS) / PROBLEMES FIXES.
-
- - reconnait '.e' aussi dans la ligne de commande
- - plusieurs érreurs fixées (et quelques nouvelles ajoutés, tant qu'on y est)
- - maintenant une variable 'stdin' existe
- - définir un PTR TO INT avec [] donne un entier non signé au lieu d'un signé
- (NOTE: ça peut changer le comportement!)
- - EC pouvait se planter avec des ENDIFs manquant : fixé.
- - CHAR s'alignait incorrectement
- - RAISE accepte des constantes négatives
- - Div() ne supportait pas les nombres négatifs
- - erreur asm en ligne: ADD.L ...,Ax devenait ADDX, quelques petits problêmes
- bêtes
- - la documentation sur StringF manquait, celle de InStr() était incorrecte
- - SIZEOF prend les CHAR/INT/LONG aussi maintenant
- - WaitIMessage() fait des choses bizarres
- - EC ne prenait pas de très grand sources (>500k)
- - un WHILE ou un UNTIL avec un IF-exp comme booléen pouvait générer un code faux
- - [exp]:CHAR créait un code faux
- - quelques érreur syntaxiquepouvait être ne pas être vu
- - la console s'ouvrait en mode READWRITE
-
- 4. D'autres changements que vous devez savoir
-
- - v2.1b l'option "-s" est enlevée
- - 'OPT' doit être mis en premier dans le source; d'autres constructions
- (comme 'CONST', 'RAISE') ont une vérifications plus stricte de leur position
- dans un source
- - EC peut générer des erreurs internes ('internal errors') dans certains cas.
- Si cela arrive, faites le moi savoir avec le source qui l'a causé
- - le mot-clef "IS" est équivalent à "RETURN" juste après un "PROC"
- - les conventions de registres de l'assembleur en ligne ont changé (voir 15B)
-
-
- Conseils aux utilisateurs de la v2.1b: comparaisons des 2 versions du fichier
- 'référence.doc'
-
-
- 0F. information additionnelle
- -----------------------------
-
- Le compilateur Amiga E a été développé sur plus 2 ans et demi, après l'idée de
- l'auteur d'un bon langage de programmation, et d'un compilateur spécifique
- Amiga de qualité pour lui. Il a été programmé (vous l'aurez deviné) 100% en
- assembleur, utilisant l'assembleur AsmOne v1.02. Tous les autres programmes
- supports ont été écrit en E même.
-
- Remerciements spécials pour les personnes suivantes:
-
- Barry Wills - pour être le meilleur bétatesteur du monde
- Jason Hulance - pour son Guide du Débutant ('The Beginners Guide'), et comme
- bétatesteurss
- Rob Verver - pour ses commentaires/inspirations
- Erwin van Breemen - comme bétatesteurs
-
- Je voudrait aussi remercier les personnes suivantes pour des raisons variées:
-
- Raymond Hoving, Michael Zuchhi, James Cooper, Jens Gelhar, Paolo Silvera,
- Jeroen Vermeulen, Jan van den Baard, Joerg Wach, Norman Kraft,
- Urban Mueller, Charles McCreary, Olivier Anh, et plein d'autres...
-
- Ce compilateur a été programmé avec une attention spécial sur la fiabilité
- et même plus sur le code généré. De plus, il a été testé et débarrassé de ses
- érreurs pour une longue période. Malgré tout, il n'est pas impossible qu'il
- contienne encore des erreurs. Si vous en trouvez, ou avez un commentaire/
- question, écrivez à l'adresse ci-dessous :
- Je préfère _de loin_ les Emails au courrier conventionnel.
-
- NOTE : Dû à l'immense popularité de la précédente version d'Amiga E,
- je recoit une quantite incroyable d'Emails auxquels je ne peux répondre.
- Certains d'entre eux (50%-75%) sont des questions qui ne devrait pas
- avoir lieu d'être si les personnes lisaient toutes les docs avec attention.
- Ce que je veux dire, c'est que j'aime recevoir des Emails, et répondre à
- des questions et aider les personnes dans leur programmation, mais consultez
- toutes les informations que vous avez à votre disposition comme les docs
- d'Amiga E ou les RKRM) pour voir si votre question est éclaircie, avant de
- m'envoyer un mots.
-
-
- Enregistrements (voir 0C) et donations sont les bienvenues à l'adresse:
-
-
- Wouter van Oortmerssen ($#%!)
- Levendaal 87
- 2311 JG Leiden
- HOLLAND
-
- ou si vous avez un accès aux Emails:
-
- wouter@alf.let.uva.nl (support programmation E)
- wouter@mars.let.uva.nl (personel)
- oortmers@gene.fwi.uva.nl (autre)
-
-
-
- +---------------------------------------------------------------+
- | 1. FORMAT |
- +---------------------------------------------------------------+
-
-
- 1A. tabs,lf etc.
- ----------------
-
- Les sources E sont de pures fichiers ASCII, avec saut de ligne <lf> et point-
- virgule ";" servant de séparateurs de déclarations. Les déclarations, qui ont
- des arguments particuliers, séparés par une virgule ",", peuvent s'étendre
- sur plus d'une ligne terminée par une virgule, ignorant alors les sauts de
- ligne.
-
-
- 1B. commentaires
- ----------------
-
- Les commentaires peuvent être placés n'importe où dans le source où
- normalement un espace aurait été correct. Ils commencent avec '/*' et se
- terminent avec '*/' et peuvent être imbriqués les uns dans les autres.
-
-
- 1C. identificateurs et types
- ----------------------------
-
- Les identificateurs sont des chaines que le programmeur utilise pour
- caractériser certains objets, dans la plupart des cas des variables, ou même
- des mots-clé ou des noms de fonction prédéfinies par le compilateur. Un
- identificateur consiste en :
-
- - caractères MAJUSCULEs et minuscules
- - "0" .. "9" (sauf pour le premier character)
- - "_" (le souligné)
-
- Tous les caractères sont significatifs, mais le compilateur ne regarde que
- les 2 premiers pour identifier le type d'identificateur avec lequel il a
- affaire :
-
- majuscule tous les deux : - mots-clé comme IF, PROC etc.
- - constantes comme MAX_LENGTH
- - mnémoniques assembleur comme MOVE
- le premier en minuscule : - identificateurs de variable/label/objet etc.
- premier en majuscule, second en minuscule :
- - fonctions système du E system comme WriteF()
- - appels de bibliothèque : OpenWindow()
-
- Notez que tous les identificateurs obéissent à cette syntaxe, par exemple :
- WBenchToFront() devient WbenchToFront()
-
-
-
- +---------------------------------------------------------------+
- | 2. VALEURS IMMEDIATES |
- +---------------------------------------------------------------+
-
- Les valeurs immédiates en E sont évaluées en 32 bits ; la seule différence
- parmi ces valeurs (A-G) est soit leur représentation interne, ou le fait qu'
- elles retournent un pointeur plutôt qu'une valeur.
-
-
- 2A. décimales (1)
- -----------------
-
- Une valeur décimales est un séquence de caractères "0"..."9", avec la
- possibilité d'être précédé par un signe moins "-" pour les chiffres négatifs.
- Exemples : 1, 100 ,-12, 1024
-
-
- 2B. héxadecimales ($1)
- ----------------------
-
- Une valeurs héxadécimales utilise les caractères "A"..."F" en plus, ou
- "a"..."f" et est précédées par un $.
- Exemples:
- $FC, $DFF180, -$ABCD
-
-
- 2C. binaires (%1)
- -----------------
-
- Les nombres binaires commencent par un "%" et n'utilise que "0" et "1" pour
- former une valeur.
- Exemples: %111, %1010100001, -%10101
-
-
- 2D. flottants (1.0)
- -------------------
-
- Les flottants diffèrent des nombres décimaux de part le "." qui les séparent
- en deux. Une des parties peut être omise, pas les 2.
- Notez que le flottants ont une représentation interne de 32bits (FFP). Reportez
- vous au chapitre 12 pour plus d'informations.
- Exemples:
- 3.14159, .1 (=0.1), 1. (=1.0)
-
-
- 2E. caractères ("a")
- ---------------------
-
- La valeur d'un caractère (encadré par des double cotes "") est leur valeurs
- ASCII, par ex. "A" = 65. En E, les valeurs immédiates des caractères doivent
- être des chaines d'au plus 4 caractères, par exemple "FORM", où le premier
- caractère "F" sera le poids fort (MSB) de la représentation 32 bits, et "M"
- le poids faible (LSB : least significant byte).
-
-
- 2F. chaines ('bla')
- -------------------
-
- Les chaines sont des représentations ASCII, encadrées pour des simple cotes.
- La valeur de ces chaines est un pointeur sur le premier caractères.
- Plus spécifique : 'bla' produit un pointeur de 32 bits dans la mémoire, où
- on trouve les octets "b, "l", "a". TOUTES les chaines en E sont terminées
- par un octet zéro (0).
- Les chaines peuvent contenir des symboles de format introduit par "\" (anti
- slash), soit pour introduire des caractères dans la chaine, qui sont pour
- quelques raisons non affichables, soit pour formatter la chaine avec les
- fonctions de format telles que WriteF(), TextF() and StringF(), ou
- sous kick2.0, Vprintf().
-
- \n saut de ligne (ascii 10)
- \a ou '' apostrophe ' (celui pour encadrer une chaine)
- \e escape (ascii 27)
- \t tabulation (ascii 9)
- \\ barre oblique inverse (anti slash)
- \0 octet zéro 0. D'utilisation rare, car les chaines
- finissant toutes par un zéro.
- \b retour chariot (carriage return) (ascii 13)
-
- De plus, quand utilisé avec les fonctions de format :
-
- \d affiche un nombre décimal
- \h affiche un nombre héxadecimal
- \s affiche une chaine
- \c affiche un caractère
- \z met l'octet de remplissage à '0'
- \l justifie le champ à gauche
- \r justifie le champ à droite
-
- Les spécificateurs de champs doivent suivrent les codes \d, \h et \s :
-
- [x] specifie un champ de largeur x
- (x,y) specifie le x minimum et le y maximum (chaine seulement)
-
- Exemple: affiche un nombre héxadécimal avec 8 caractères laissant la place
- aux zéros :
- WriteF('\z\h[8]\n',num)
-
- Une chaine peut-être étendue sur plusieurs ligne en insérant entre eux un "+"
- et un saut de ligne (lf) :
-
- 'Ceux sont 2 longues lignes ' +
- 'qui sont mises sur 2 lignes'
-
-
- 2G. listes ([1,2,3]) et listes typées
- -------------------------------------
-
- Une liste immédiate est la partie constante du type LISTe, comme une 'chaine'
- est la partie constante pour une chaine ou un tableau de caractères (ARRAY OF
- TYPE).
- Exemple :
-
- [3,2,1,4]
-
- est une expression qui a comme valeur un PoinTeuR sur une liste initialisée,
- une liste comme représentation en mémoire est compatible avec un tableau
- (ARRAY OF LONG), avec quelques informations en plus en offset négatif. Vous
- devez utiliser ces listes immédiates n'importe où, où une fonction demande un
- pointeur sur un tableau de valeurs 32bits, ou une liste.
- Exemple :
-
- ['chaine',1.0,2.1]
- [WA_FLAGS,1,WA_IDCMP,$200,WA_WIDTH,120,WA_HEIGHT,150,TAG_DONE]
-
- Voir la partie sur les fonctions de liste pour différencier les listes
- immédiates et typées, et pour des informations détailées.
-
-
-
- +---------------------------------------------------------------+
- | 3. EXPRESSIONS |
- +---------------------------------------------------------------+
-
-
- 3A. format
- ----------
-
- Une expression est un morceau de code lié par des opérateurs, fonctions et
- parenthèses pour former une valeur.
- Il consiste dans la plupart des cas en :
-
- - des valeurs immédiates (chapitre 2)
- - des opérateurs (chapitre 4)
- - des appels de fonction (chapitre 3D)
- - des parenthèses () (chapitre 3B)
- - des variables ou des expressions-variables (chapitre 3C)
-
- Exemples d'expressions :
-
- 1
- 'hello'
- $ABCD+(2*6)+Abs(a)
- (a<1) OR (b>=100)
-
-
- 3B. priorité des opérateurs
- ---------------------------
-
- Le langage E n'a pas de priorité. Cela signifie que les expressions
- sont évaluées de gauche vers la droite. Vous pouvez changer cette priorité
- en mettant entre parenthèses des (sous-)expressions :
- 1+2*3 /* =9 */ 1+(2*3) /* =7 */ 2*3+1 /* =7 */
-
-
- 3C. types d'expressions
- -----------------------
-
- Il y a 3 types d'expressions qui peuvent être utilisés pour différentes
- applications :
-
- - <var>, juste une variable
- - <varexp>, un variable, avec un opérateurs unaire possible
- comme ++ (incrémentation) ou [] (opérateur de tableau). Pour cela,
- voir les chapitre 4D et 4G. Il caractérise un expression modifiable
- comme Lvaleur en C.
- Notez que ces opérateurs unaires ne font pas partie des priorité.
- - <exp>. Cela inclue <var> et <varexp>, et n'importe quelle autre
- expression.
-
-
- 3D. appels de fonction
- ----------------------
-
- Un appel de fonction est arrêt temporaire du code pour un saut vers une
- fonction, qui peut-être une procédure (PROC), ou juste une fonction du
- système. Le format d'un appel de fonction est le nom de la fonction, suivit
- par 2 parenthèses () encadrant de zéro à un nombre illimité d'argument,
- séparés par des virgules ",".
- Notez que les arguments de fonctions sont des expressions.
- Voir le chapitre 6 pour savoir comment faire sa propre fonction, et chapitre
- 9 et 10 pour les fonctions prédéfinis.
- Exemples :
-
- foo(1,2)
- Gadget(buffer,glist,2,0,40,80+offset,100,'Cancel')
- Close(handle)
-
-
-
- +---------------------------------------------------------------+
- | 4. OPERATEURS |
- +---------------------------------------------------------------+
-
-
- 4A. mathématiques (+ - * /)
- ---------------------------
-
- Ces opérateurs combinent une expression à un autre valeur pour produire une
- nouvelle valeur.
- Exemples :
-
- 1+2, MAX-1*5
-
- Voir le chapitre 12 pour savoir comment utiliser les opérateurs sur les
- flottants.
- Le "-" peut être utilisé en première d'expression, avec un 0 implicite,
- par ex. -a ou -b+1 sont egaux.
- Notez que * et / sont par défaut des opérateurs 16 bits : Voir Mul()
-
-
- 4B. comparaison (= <> > < >= <=)
- --------------------------------
-
- Idem aux opérateurs mathématiques, à la différence qu'ils renvoient soit VRAI
- (TRUE, valeur 32 bits = -1), ou FAUX (FALSE =0). Ils peuvent être surpassé
- par les flottants.
-
-
- 4C. logique (AND et OR)
- -----------------------
-
- Ces opérateurs soit combinent des valeurs vraies en de nouvelles, soit
- réalisent des opérateurs sur des bits AND et OR.
- Exemples :
-
- (a>1) AND ((b=2) OR (c>=3)) /* logique */
- a:=b AND $FF /* opérateur de bits */
-
-
- 4D. unaire (SIZEOF ^ {} ++ -- `)
- --------------------------------
-
- - SIZEOF <objet>
- retourne simplement la taille d'un objet.
- Exemple: SIZEOF newscreen
- - {<var>}
- retourne l'adresse d'une variable ou d'un label. C'est cet opérateur que
- vous utiliserez pour donner une variable comme argument à une fonction par
- référence, et non pas par valeur, ce qui est le défaut en E. Voir "^".
- Exemple: Val(input,{x})
- - ^<var>
- A l'inverse de {}, il écrit ou lit des variables qui sont donnés par
- référence.
- Examples: ^a:=1 b:=^a
- Il est alors utilisé pour aller chercher (peek) et poser (poke) des valeurs
- LONG en mémoire, si <var> est un pointeur sur cette valeur.
- Exemple pour {} et ^: écrit votre fonction d'assignement :
-
- PROC set(var,exp)
- ^var:=exp
- ENDPROC
-
- et appelez le avec : set({a},1) /* egale a:=1 */
- - <varexp>++ et <varexp>--
- Incréménte (++) ou décrémente (--) le pointeur caractérisé par <varexp> par
- par la taille des données vers lequel il pointe. Cela a pour effet que ce
- pointeur pointe vers l'article (item) suivant ou précédent. Quand il est
- utilisé sur des variables qui ne sont pas des pointeurs, il changera
- simplement en 1. Notez que ++ prend effet _après_ le calcul de <varexp>, et
- -- toujours _avant_.
- Exemples :
-
- a++ /* retourne la valeur de a, et l'incrémente de 1 */
- sp[]-- /* décrémente le pointeur sp de 4 (si il y avait un tableau),
- et lit la valeur pointée par sp */
- - `<exp>
- On appelle un telle expression, un expression cotée, venant du LISP. <exp>
- n'est pas évaluée, mais retourne l'adresse de l'expression, qui peut être
- plus tard évaluéeau moment voulu. Voir le chapitre 11 pour plus
- d'informations.
-
-
- 4E. triple (IF THEN ELSE)
- -------------------------
-
- L'opérateur IF a presque la même fonction que la déclaration IF, seulement il
- choisit entre 2 expressions au lieu de 2 déclarations ou blocs de code.
- Il est équivalant à l'opérateur x?y:z en C.
-
- IF <boolexp> THEN <exp1> ELSE <exp2>
-
- retourne exp1 ou exp2, suivant l'expression booléenne boolexp. Par exemple,
- au lieu de :
-
- IF a<1 THEN b:=2 ELSE b:=3
- IF x=3 THEN WriteF('x égale 3\n') ELSE WriteF('x égale autre chose\n')
-
- écrivez:
-
- b:=IF a<1 THEN 2 ELSE 3
- WriteF(IF x=3 THEN 'x égale 3\n' ELSE 'x égale autre chose\n')
-
-
- 4F. structures (.)
- -----------------
-
- <ptr2object>.<memberofobject> forme une <varexp>
- Le pointeur doit être déclaré comme PTR TO <objet> ou ARRAY OF <objet>
- (voir le chapitre 8 pour cela), et le membre doit être un identificateur
- d'un objet déclaré. Notez que lire un sous objet d'un objet comme cela
- donne un pointeur sur cet objet.
- Exemple :
-
- cettetache.userdata:=1
- rast:=monecran.rastport
-
-
- 4G. tableaux ([])
- -----------------
-
- <var>[<indexexp>] (est une <varexp>)
- Cet opérateur lit la valeur d'un tableau sur lequel <var> pointe, et avec
- pour index <indexexp>. Cet index peut être simplement une expression, avec un
- petite limitation : il ne doit pas contenir des appels de fonction quand
- utilisé sur la partie gauche de l'assignement.
- Note 1 : "[]" est un raccourcit de "[0]"
- Note 2 : avec un tableau de n éléments, l'index va de 0 .. n-1
- Exemples:
-
- a[1]:=10 /* met le second élément à 10 */
- x:=table[y*4+1] /* lit le tableau */
-
-
- 4H. opérateurs flottants (|)
- ----------------------------
-
- <exp>|<exp>
- Convertis des expressions d'entier en flottants et inversement, et surpasse
- les opérateurs + - * / = <> < > <= >= avec les équivalents flottants.
- Voir le chapitre 12 pour tout savoir sur les flottants et cet opérateur.
-
-
- 4I. expressions d'assignements (:=)
- -----------------------------------
-
- Les assignements (donner une valeur a une variable) existe comme déclaration
- et comme expression. La seule différence est que la déclaration est de la forme
- <varexp>:=<exp> et l'expression <var>:=<exp>.
- Ce dernier a la valeur <exp> comme résultats.
- Notez que comme <var>:= prend une expression, vous aurez souvent besoin de
- parenthèses pour forcer la bonne interprétation, comme :
-
- IF mem:=New(100)=NIL THEN error()
-
- est interprété comme :
-
- IF mem:=(New(100)=NIL) THEN error()
-
- ce qui n'est pas ce qu'on veut : mem doit être un pointeur, pas un booléen.
- On doit écrire :
-
- IF (mem:=New(100))=NIL THEN error()
-
-
- 4J. séquence (BUT)
- -------------------
-
- L'opérateur de séquence "BUT" vous permet d'écrire 2 expressions dans une
- construction n'en acceptnt qu'une seule. Souvent en écrivant de complexes
- appels de fonction, on voudrait faire une autre action 'à la volée', comme
- un assignement :
-
- <exp1> BUT <exp1>
-
- Cela veux dire : évalue exp1, mais retourne la valeur de exp2.
- Exemple:
-
- mafonction((x:=2) BUT x*x)
-
- assigne 2 à x, et appelle la fonction mafonction avec x*x. Les () autour
- de l'assignementsont nécessaire pour prévenir l'opérateur := qu'il s'agit
- d'une expression.
-
-
-
- +---------------------------------------------------------------+
- | 5. DECLARATIONS |
- +---------------------------------------------------------------+
-
-
- 5A. format (;)
- --------------
-
- Comme suggéré au chapitre 1A, une déclaration est en général mise sur sa
- propre ligne, mais plusieurs peuvent être mise ensemble sur une seule ligne,
- en les séparant par un point-virgule ";", ou bien une déclaration peut être
- étendue sur plus d'une ligne, celles-ci finissant par une virgule.
- Exemples :
-
- a:=1; WriteF('salut!\n')
- DEF a,b,c,d, /* trop d'arguments sur la ligne */
- e,f,g
-
- Les déclarations peuvent être :
- - des assignements
- - des déclarations conditionelles, voir aussi les chapitres 5E-5K
- - des expressions vides
- - des labels
- - des instructions assembleurs
-
- La virgule est le premier caractère montrant uevous ne voulez pas terminer la
- déclaration avec le prochain saut de ligne (lf), mais les caractères suivants
- signalent la suite de la déclaration sur la ligne suivante :
-
- + - * /
- = > < <> >= <=
- AND OR BUT THEN
-
-
- 5B. déclarations de labels et gotos (JUMP)
- ------------------------------------------
-
- Les labels sont des identificateurs globals avec un ":" à la fin :
-
- monlabel:
-
- Ils peuvent être utilisés par des instructions comme JUMP, et comme référence
- de données statiques. Ils peuvent être utilisés pour sortir de tous types de
- boucles (cette technique n'est pas recommandée), mais pas en dehors de
- procédures. Dans un programme E normal, ils sont souvent utilisés dans les
- lignes assembleurs.
- Les labels sont toujours très visible.
-
- JUMP <label>
-
- continue l'éxécution à prtir du <label>. Vous n'êtes pas encouragé à utiliser
- cette instruction, elle est là pour des situations qui devrait augmenter la
- compléxité du programme si elle n'était pas là.
- Exemple :
-
- IF Mouse()=1 THEN JUMP stopmaintenant
-
- /* suite du programme */
-
- stopmaintenant:
-
-
- 5C. assignement (:=)
- --------------------
-
- Le format de base d'un assignement est : <var> := <exp>
- Exemples:
-
- a:=1
- a:=mafonction()
- a:=b*3
-
-
- 5D. mnémoniques assembleurs
- ---------------------------
-
- En E, les lignes assembleurs font partie intégrante du langage, elles n'ont
- pas besoin d'être encadré dans un blocs "ASM" spécial, comme il est usuel
- dans d'autres langages, ni être assemblé par un assembleur externe pour
- assembler le code. Cela veut dire qu'elles obéissent aux règles de syntaxe
- du E, etc. Voir le chapitre 15 pour plus de détails.
- Exemple :
-
- DEF a,b
- b:=2
- MOVEQ #1,D0 /* quelques lignes assembleurs */
- MOVE.L D0,a /* a:=1+b */
- ADD.L b,a
- WriteF('a=\d\n',a) /* a sera égal à 3 */
-
-
- 5E. déclaration conditionelle (IF)
- ----------------------------------
-
- IF, THEN, ELSE, ELSEIF, ENDIF
-
- syntaxe: IF <exp> THEN <déclaration> [ ELSE <instruction> ]
- ou: IF <exp>
- <instructions>
- [ ELSEIF <exp> /* plusieurs elseif peuvent */
- <instructions> ] /* avoir lieu */
- [ ELSE ]
- <instructions>
- ENDIF
-
- construit un bloc conditionnel. Notez qu'il y a 2 formes générales de cette
- déclaration, en ligne unique et en ligne étendue.
-
-
- 5F. instruction for (FOR)
- -------------------------
-
- FOR, TO, STEP, DO, ENDFOR
-
- syntaxe: FOR <var> := <exp> TO <exp> STEP <pas> DO <instruction>
- ou: FOR <var> := <exp> TO <exp> STEP <pas>
- <instructions>
- ENDFOR
-
- construit une boucle FOR. Notez les 2 formes générales. <pas> est une
- constante positive ou négative, à l'exclusion de 0.
- Exemple :
-
- FOR a:=1 TO 10 DO WriteF('\d\n',a)
-
-
- 5G. intruction while (WHILE)
- ----------------------------
-
- WHILE, DO, ENDWHILE
-
- syntaxe: WHILE <exp> DO <instruction>
- ou: WHILE <exp>
- <instructions>
- ENDWHILE
-
- construit une boucle while, qui est répétée tant que <exp> est vraie (TRUE).
- Notez les 2 formes générales.
-
-
- 5H. instruction repeat (REPEAT)
- -------------------------------
-
- REPEAT, UNTIL
-
- syntaxe: REPEAT
- UNTIL <exp>
-
- contruit un block en boucle repeat-until : la boucle sera répétée jusqu'à ce
- que <exp> soit vraie (TRUE) .
- Exemple :
-
- REPEAT
- WriteF('Vous voulez vraiment sortir du programme ?\n')
- ReadStr(stdout,s)
- UNTIL StrCmp(s,'oui !')
-
-
- 5I. instruction loop (LOOP)
- ---------------------------
-
- LOOP, ENDLOOP
-
- syntaxe: LOOP
- <instructions>
- ENDLOOP
-
- construit une boucle infinie.
-
-
- 5J. instruction select-case (SELECT)
- ------------------------------------
-
- SELECT, CASE, DEFAULT, ENDSELECT
-
- syntax:e SELECT <var>
- [ CASE <exp>
- <intructions> ]
- [ CASE <exp>
- <instructions> ] /* autant de bloc de ce type */
- [ DEFAULT
- <instructions> ]
- ENDSELECT
-
- construit un bloc select-case. De nombreuses expressions vont être comparées
- à la variable, et seulement le premier bon bloc sera éxécuté. Si rien n'est
- trouvé, le bloc par défaut est éxécuté.
-
- SELECT caractère
- CASE 10
- WriteF('He, j'ai trouvé un saut de ligne\n')
- CASE 9
- WriteF('Ouah, ca doit être une tabulation!\n')
- DEFAULT
- WriteF('Vous connaissez celui là : \c ?\n',caractère)
- ENDSELECT
-
-
- 5K. instruction d'incrémentation (INC/DEC)
- ------------------------------------------
-
- INC, DEC
-
- syntaxe: INC <var>
- DEC <var>
-
- raccourcit de <var>:=<var>+1 et <var>:=<var>-1. La seule différence avec
- <var>++ et <var>-- est que INC et DEC sont des instructions, et ne retourne
- aucune valeur, et sont plus efficient.
-
-
- 5L. expressions vide (VOID)
- ---------------------------
-
- VOID
-
- syntaxe: VOID <exp>
-
- calcule l'expression sans que le résultat n'aille quelque part. Utile
- seulement pour une syntaxe claire, comme les expressions peuvent être
- utilisées comme intruction sans VOID en E ! Cela peut provoquer une subtile
- érreur : alors que "a:=1" assigne à a la valeur 1, "a=1" est une instruction
- qui ne fait rien. E vous le signalera si cela arrive.
-
-
-
- +---------------------------------------------------------------+
- | 6. DEFINITIONS DE FONCTIONS ET DECLARATIONS |
- +---------------------------------------------------------------+
-
-
- 6A. définition et arguments des procédures (PROC)
- -------------------------------------------------
-
- Vous devez utiliser PROC et ENDPROC pour définir les instructions dans vos
- propres fonction. Ces fonctions peuvent avoir plusieurs arguments, mais
- retourne une seule valeur.
-
- syntaxe: PROC <label> ( <args> , ... )
- ENDPROC <valeur_retournée>
-
- définie une procédure avec un nombre d'arguments. Les arguments sont de type
- LONG ou de type PTR TO <type> (voir chapitre 8) et n'ont pas besoin d'autre
- déclaration.
- La fin de la procédure est désigné par ENDPROC. Si aucune valeur n'est donnée,
- 0 est retournée.
- Exemple : écrire une fonction qui retourne la somme de 2 arguments :
-
-
- PROC add(x,y) /* x et y sont des variables locales */
- ENDPROC x+y /* retourne le résultat */
-
-
- 6B. définitions locales and globales (DEF)
- ------------------------------------------
-
- Vous devez définir des variables locales en plus de celles qui sont définies
- avec DEF. Le plus simple est :
-
- DEF a,b,c
-
- déclare les identificateurs a, b et c de votre fonction.
- Notez que ces déclarations doivent être au début de votre fonction.
-
- syntaxe: DEF <déclarations>,...
- description: déclare les variables. Une déclaration est une de ces formes:
- <var>
- <var>:<type> where <type>=LONG,<objet>
- <var>[<taille>]:<type> where <type>=ARRAY,STRING,LIST
-
- Voir le chapitre 8 pour plus d'exemples, c'est là que les types sont introduit.
- A partir de maintenant, on utilisera l'écriture <var>.
- Les arguments de fonctions sont réduits aux types simples : voir chapitre 8B.
- Une déclaration de type simple peut avoir une initiaisation. Dans cette
- version elle doit être faite par un entier (pas d'expression) :
-
- DEF a=1,b=2
-
- Un programme consiste en une suite de fonctions, appellé procédures, PROC.
- Chacune d'elles puevent avoir des variables locales, et le programme en son
- entier, peut avoir des variables globales. Enfin, une procédure doit être
- un PROC main(), car c'est cette procédure qui est éxécutée en premier. Un
- programme simple peut ressembler à ça :
-
- DEF a, b /* définition des variables globales */
-
- PROC main() /* l'ordre des fonctions peut être */
- bla(1) /* mis au hasard */
- ENDPROC
-
- PROC bla(x)
- DEF y,z /* possibilité de variables locales */
- ENDPROC
-
- Pour résumer, les définitions locales sont celles que vous faites au début
- des procédures, et qui ne sont visible qu'à l'intérieure de celles-ci.
- Les définitions globales sont faites avant le premier PROC, au début de votre
- source, et ils sont visibles dans toutes les procédures.
- Les variables globales et locales (et bien sûr les variables locales de 2
- différentes fonctions) peuvent avoir le même nom ; les variables locales ont
- toujours la priorité sout les variables globales.
-
-
- 6C. endproc/return
- ------------------
-
- Comme décrit plus haut, ENDPROC marque la fin d'une définition de fonction, et
- peuvent retourner une valeur. De plus RETURN peux être utilisé n'importe où
- dans la fonction pour en sortir. Si il est utilisé dans la procédure main(),
- on sortira du programme. Voir aussi CleanUp() au chapitre 9F.
-
- RETURN [<valeur_retournée>] /* optionel */
-
- Exemple:
-
- PROC getresources()
- /* ... */
- IF error THEN RETURN FALSE /* quelque s'est mal passé, on sort */
- /* ... */
- ENDPROC TRUE /* on est allé aussi loin, on retourne TRUE */
-
- Une version très raccourcit d'un définition de fonction peu-être :
-
- PROC <label> ( <arg> , ... ) RETURN <exp>
-
- Ce sont des définitions de fonctions qui ont besoin de peu de calcul, comme
- les fonctions de puissances et associé : (en une ligne :-)
-
- PROC fac(n) RETURN IF n=1 THEN 1 ELSE fac(n-1)*n
-
-
- 6D. la fonction "main"
- ----------------------
-
- La procédure appelée main a son importance, car elle est appelé en première ;
- elle fonctionne de la même minère que les autres fontions, et peut donc avoir
- des variables locales. Main n'a pas d'arguments : les arguments de la ligne
- de commande (du shell) sont fournis par la variable système "arg", ou peuvent
- être collectée avec ReadArgs().
-
-
- 6E. variables système prédéfinies (built-in)
- --------------------------------------------
-
- Les variables globales suivantes sont toujours accessible au sein du programme.
- Ils sont appellés variables système :
-
- arg Vu plus haut, arg contient un pointeur sur une chaine terminée
- par un zéro. arg contient les arguments de la ligne de
- commande. Ne l'utilisez pas si vous voulez utiliser ReadArgs().
- stdout Contient le gestionnaire de fichier de la sortie et de
- l'entrée standard. Si votre programme est lancé du workbench,
- aucune sortie shell n'est possible. WriteF() ouvrira une
- fenêtre CON: pour vous, et mettra son gestionnaire là.
- conout Ces de là que le gestionnaire de fichier est pris et la
- fenêtre console sera automatiquement fermée à la fin de votre
- programme. Voir WriteF() dans le chapitre 9A pour savoir
- comment utiliser proprement les variables.
- execbase, Ces 5 variables sont toujours définies avec leur valeur
- dosbase, correcte.
- gfxbase,
- intuitionbase,
- mathbase
- stdrast Pointeur sur le rastport standard utilisé dans votre
- programme, ou bien NIL. Les fonctions graphique prédéfinies
- comme Line() utilisent cette variable.
- wbmessage Contient un pointeur sur un message reçu si le programme est
- lancé du workbench, sinon NIL. Il peut être utilisé comme
- variable booléenne pour détecter si vous vous êtes partis du
- workbench, ou pour pour collecter les arguments d'éventuelles
- icones cliquées. Voir le programme WbArgs.e dans le
- répertoire sources/exemples, pour savoir comment bien
- l'utiliser.
-
-
-
- +---------------------------------------------------------------+
- | 7. DECLARATION DE CONSTANTES |
- +---------------------------------------------------------------+
-
-
- 7A. constantes (CONST)
- ----------------------
-
- syntaxe: CONST <déclarations>,...
-
- Vous permet de déclarer une constante. Une déclaration ressemble à :
- <ident>=<valeur>
-
- Les constantes doivent être en majuscule, et seront traité dans le reste du
- programme comme <valeur>.
- Exemple :
-
- CONST MAX_LINES=100, ER_NOMEM=1, ER_NOFILE=2
-
- Vous ne pouvez pas déclarer des constantes dans les mêmes termes qu'une autres
- dans la même instruction CONST. Mettez le dans une autre.
-
-
- 7B. énumerations (ENUM)
- -----------------------
-
- Les énumérations sont un type de constante particulier, qui n'ont pas besoin
- de valeur, car ils sont définis de 0 à n ; le premier étant égal à zéro. A
- n'importe quel moment de l'énumération, vous pouvez utiliser la notation
- '=<valeur>' pour fixer ou remettre à zéro le compteur.
- Exemple :
-
- ENUM ZERO, ONE, TWO, THREE, MONDAY=1, TUESDAY, WEDNESDAY
-
- ENUM ER_NOFILE=100, ER_NOMEM, ER_NOWINDOW
-
-
- 7C. sets (SET)
- --------------
-
- Les sets sont du même type que les énumérations, à la différence qu'au lieu
- d'augmenter leur valeur (0,1,2,...), on augmenter leur nombre de bit
- (0,1,2,...) et donc leur valeur deviennent (1,2,4,8,...). Cela a pour avantage
- qu'ils peuvent être utilisés comme des drapeaux (flags).
- Supposez un set comme celui--ci pour décrire les propriété d'un fenétre :
-
- SET SIZEGAD,CLOSEGAD,SCROLLBAR,DEPTH
-
- pour initialiser une variable au pripriété DEPTH et SIZEGAD :
-
- winflags:=DEPTH OR SIZEGAD
-
- pour ajouter un SCROLLBAR :
-
- winflags:=winflags OR SCROLLBAR
-
- et pour tester si 2 propriétés sont pris en compte :
-
- IF winflags AND (SCROLLBAR OR DEPTH) THEN /* ... */
-
-
- 7D. constantes prédéfinies (built-in)
- -------------------------------------
-
- Les constantes suivantes sont prédéfinies et peuvent être utilisées :
-
- TRUE,FALSE Représente les valeurs booléennes (-1,0)
- NIL (=0), le poineur non initialisé
- ALL Utilisé avec les fonctions de chaine comme StrCopy() pour
- copier tous les caractères
- GADGETSIZE taille minimum en octets nécessaire pour définir un gadget ;
- voir Gadget() au chapitre 9D
- OLDFILE,NEWFILE Paramètres de mode à utiliser avec Open()
- STRLEN A toujours la longueur de la dernière chaine utilisée.
- Exemple :
-
- Write(handle,'Salut tous le monde!',STRLEN) /* =20 */
-
-
-
- +---------------------------------------------------------------+
- | 8. TYPES |
- +---------------------------------------------------------------+
-
-
- 8A. à propos du système "type"
- ------------------------------
-
- Le E n'a pas une système de type rigid comme le Pascal ou le Modula2, il est
- même plus flexible que clui du C : on doit plutôt l'appeler un système de type
- de donnée (datatype system). Il en résulte qu'en E tous les types de données
- sont égaux : toutes les valeurs simples comme les carctères, entiers, etc.
- Ils ont tous la même taille de 32 bits, et les autres types comme les tableaux,
- les chaines sont représentées par des pointeurs de 32 bits pointant sur eux.
- Ainsi, le compilateur E peut générer un code de façon très polymorphe.
- Les (dés)avantages sont nombreux :
-
- désavantages :
-
- - peu de vérification sur des érreurs que vous faites.
-
- avantages :
-
- - polymorphisme de bas niveau,
- - programmation très flexible : aucune crainte de voir certaines valeurs
- retournées, ne correspondant pas à la variable cible, etc.,
- - facilité de retrouver des érreurs lors de mélange de données
- d'expressions de taille différentes,
- - bénéficie de types 'auto-documentés', si vous voulez comme ça :
-
- PTR to newscreen
-
-
- 8B. le type simple (LONG/PTR)
- -----------------------------
-
- Il n'y a qu'un seul simple et non-complexe type en E, qui est le type
- LONG de 32 bits. Comme c'est le type par défaut, il peut être déclaré comme :
-
- DEF a:LONG ou juste: DEF a
-
- Ce type de variable a les mêmes caractèristiques que les types
- CHAR/INT/OTR/LONG d'autres langages. Un variation de LONG est le type pointeur
- PTR. Ce type est compatible avec le LONG, à la différence qu'il est spécifié
- en tant que pointeur. Par défaut, le type LONG est spécifié comme PTR TO CHAR.
-
- Syntaxe: DEF <var>:PTR TO <type>
-
- où le <type> est de type simple ou composé.
- Exemple :
-
- DEF x:PTR TO INT, mon_écran:PTR TO screen
-
- Notez que 'screen' est le nom d'un objet défini par le module
- 'intuition/screens.m'. Par exemple, si vous ouvrez votre propre écran avec :
-
- mon_écran:=OpenS(... etc.
-
- vous devez utiliser le pointeur mon_écran tout comme 'mon_écran.rastport'.
- Si vous ne voulez pas utiliser cette variable jusqu'à la fermeture de l'écran
- par CloseS(mon_écran), vous pouvez simplement le déclarer comme :
-
- DEF mon_écran
-
-
- 8C. le type simple (CHAR/INT/LONG)
- ----------------------------------
-
- Les types simples CHAR (8 bits) et INT (16 bits) ne doivent pas être utilisés
- pour des variables de base. La raison de cela doit être clair maintenant.
- Malgré tout, ils peuvent être utilisés comme type de données pour construire
- des tableaux, ou poser des pointeurs, ou être utilisé dans des objets, etc.
-
-
- 8D. le type tableau (ARRAY)
- ---------------------------
-
- Les tableaux sont déclarés en spécifiant leur longueur en octets :
-
- DEF b[100]:ARRAY
-
- définie un tableaux de 100 octets. De façon interne, b est une variable de type
- LONG et un pointeur sur cet espace mémoire.
- Le type par défaut d'un élément du tableau est CHAR, mais peut être autre
- chose en le spécifiant :
-
- DEF x[100]:ARRAY OF LONG
- DEF mes_menus[10]:ARRAY OF newmenu
-
- où 'newmenu' est une exemple de structure (appelé OBJEcT en E).
- L'accès au tableau est très simple :
- <var>[<exp>]
- Exemples :
-
- b[1]:="a"
- z:=mes_menus[a+1].mutualexclude
-
- Notez que l'index d'un tableau de taille n, est définis de 0 à n-1,
- et pas de 1 à n.
- Notez que les tableaux de type x (ARRAY OF <type>) est compatible avec les
- pointeurs sur un type x (PTR TO <type>, à la différence que la variable
- tableau est déja initialisée.
-
-
- 8E. le type complexe (STRING/LIST)
- ----------------------------------
-
- - STRING (chaine). Similaire aux tableaux, mais différent dans le sens
- qu'elles ne peuvent être modifiées que par les fonctions de chaines du E,
- et qu'ils contiennent les informations de longueurs (length et maxlength).
- Ainsi les fonctions de chaines peuvent les modifier sans crainte : la
- chaine ne peut pas être plus grande que l'espace mémoire où elle est.
-
- Syntaxe : DEF s[80]:STRING
-
- Le type de données STRING est rétroactivement compatible avec PTR TO CHAR
- et bien sûr ARRAY TO CHAR, et c'est tout.
- Voir la chapitre sur les fonctions de chaines pour plus de détails.
-
- - LIST (liste). C'est un type de donnée que l'on ne retrouve que dans
- d'autres langages comme le Prolog ou le Lisp. La version E peut être
- interprétée comme un mélange de chaine et de tableaux de LONG :
- cette structure de données est une liste de variables LONG qui peuvent
- être étendu ou résumé à des chaines.
-
- Syntaxe : DEF x[100]:LIST
-
- Un plus puissant à ce type de données est qu'il a un équivalent 'constant'
- [], comme les chaines ont ''. Les listes sont rétroactivement compatible
- avec PTR TO lONG et bien sûr ARRAY OF LONG, et c'est tout.
- Voir les chapitres 2G et 9C pour plus d'informations.
-
-
- 8F. le type composé (OBJECT)
- ----------------------------
-
- Les objets sont l'équivalent des structures en C ou RECORD en Pascal.
- Exemple :
-
- OBJECT myobj
- a:LONG
- b:CHAR
- c:INT
- ENDOBJECT
-
- définie une structure de données de 3 éléments.
-
- Syntaxe: OBJECT <nom_objet>
- <nom_membre> [ : <type> ] /* autant que vous voulez */
- ENDOBJECT
-
- où le type est un type simple ou composé, ou un tableau simple :
- [<nb_éléments>]:ARRAY avec par défaut, la taille CHAR pour un élément.
- Notez que <nom_membre> peut ne pas être seul, et peut se trouver dans
- d'autres objets. Il y a beaucoup de manière d'utiliser les objets :
-
- DEF x:mon_objet /* x est une structure */
- DEF y:PTR TO mon_objet /* y est juste un pointer dessus */
- DEF z[10]:ARRAY OF mon_objet
-
- y:=[-1,"a",100]:myobj /* listes typées */
-
- IF y.b="a" THEN /* ... */
-
- z[4].c:=z[d+1].b++
-
- Les tableaux dans les objets sont toujours arrondis à la taille paire,
- et mis sur des offsets pairs :
-
- OBJECT machaine
- longueur:CHAR,
- donnée[9]:ARRAY
- ENDOBJECT
-
- La taille (SIZEOF) de 'machaine' est de 12, et 'donnée' commence à
- l'offset 2.
-
- NOTE : les objet du E ne sont pas ce que vous imaginez dans d'autres
- langages. Par exemple, pas seulement les types peuvent former un membre
- d'un objet, et grace à ça, des accès récursif aux objets comme x.y.z
- non aucun sens (pour le moment).
-
-
- 8G. initialisation
- ------------------
-
- 1. Sont toujours initialisées à NIL (or autres, si explicitement décrit)
- - les variables globales,
- NOTE : pour une bonne documentation, il est conseillé d'écrire
- xxx =NIL dans la définition de variables qui vous voulez l'avoir nulle
- 2. Sont initialisées à '' et respectivement []
- - les chaines globales et locales
- - les listes globales et locales
- 3. Ne sont pas initialisés
- - les variables locales (tant qu'elle ne sont pas définies explicitement)
- - les tableaux globals et locaux
- - les objets globals et locaux
-
-
- 8H. l'essentiel du système de type du E
- ---------------------------------------
-
- Cette section essaie d'expliquer comment le système de type du E d'un point
- de vue différent.
-
- La plupart des problêmes que les gens ont en programmant en E provient de
- leur mauvaise connaissance sur le fonctionnement du système de type E. De même,
- beaucoup d'entre-eux ont une idée sur le fonctionnement provenant d'un autre
- langage, et essaye de l'appliqué en E, ce qui est souvent fatal, car le E est
- tout différent quant on en vient aux types.
-
- Le système de type:
- le E est par essense un langage SANS type. En fait des variables peuvent
- avoir un type, mais il est alors uniquement utilisé comme spécifications
- sur la définition d'une variable lorsqu'il est utilisé comme pointeur. Dans
- quasiment TOUS les autres contructions des langages, les variables sont
- traités comme étant du même type, code sur une valeur sans type de 32 bits.
-
- En pratique cela signifie que par exemple dans des expressions avec des
- exceptions des opérateurs ".", "[]" et "++" etc., tous les opérateurs et
- fonctions travaillent sur des valeurs sur 32 bits, sans regarder si c'est
- un booléens, entiers, réels, pointeurs sur quelquechose.
-
- Les types de pointeur:
- Dans le système de type, seulement 4 types existent, PTR TO CHAR,
- PTR TO INT, PTR TO LONG et PTR TO <objet>, où <objet> est le nom d'un
- OBJECT défini précédemment. Quand une variable (où un membre d'un object,
- comme on le verra plus tard) est déclarée comme étant de ce type. Ca
- signifie que si la variable contient une valeur qui est un pointeur legal,
- c'est comment il doit être définit.
-
- LONG, ARRAY etc.
- Tous les autres types qu'on peut voir dans les déclarations DEF ne sont
- pas réellement des types, car c'est une autre façon d'écrire un des 4
- types. Comme exemple, AEEAY OF <type> est juste une autre façon d'écrire
- PTR TO <type>, avec la seule différence que le premier est automatiquement
- assigné à une adresse d'un espace de pile suffisamment grand pour prendre
- les données du nombre d'éléments spécifiés entre crochets.
-
- Ci-dessous se trouve une table qui montre tous les 'types' E en termes des 4
- de bases:
-
- ARRAY OF CHAR, ARRAY, STRING, LONG (sont égals à) PTR TO CHAR
- ARRAY OF INT (est égale to) PTR TO INT
- ARRAY OF LONG, LIST (sont égale à) PTR TO LONG
- ARRAY OF <objet>, <objet> (sont égale à) PTR TO <objet>
-
- - LONG est pour les variables qui ne sont pas utilisé comme pointeur,
- i.e entiers. Son équivalence avec PTR TO CHAR est logique, car sur le
- plan du concept, tous 2 parlent de choses mesuré en unité 1.
- (par exemple, "++" a le même effet sur les 2)
- - LIST et STRING sont les mêmes que leurs équivalents tableaux ('ARRAY'),
- à part le fait qu'ils sont initialisés dans un morceau de la pile, mais
- leur représentation dans la pile est un petit peu plus complexe pour
- faciliter la vérification pendant le runtime ('runtime bounds-checking')
- (quand utilisé avec les bonnes fonctions).
- - un <objet> est équivalent à [1]:ARRAY OF <objet>. Tous 2 représentent un
- PTR TO <objet> initialisés.
-
- Dans un OBJECT, on peut avoir les mêmes déclarations, avec l'ajout de CHAR
- et INT 'similaire à LONG), et l'ommission de LIST et STRING, comme ils sont
- des objets complexes de leur plein droit, et ne peuvent être partis d'un objet.
-
- Définition:
- Ayant un pointeur p d'un type donné,
-
- "[]" peut indéxer d'autres éléments qui sont séquentiellement ordonnés après
- l'élément qui est actuellement pointé. Notez qu'il permet des indices
- positifs et négatifs, et aussi aucune supposition n'est faites sur où et
- combien d'éléments sont actuellement alloués.
-
- "++" mets le pointeur sur l'élément suivant en mémoire, "--" sur l'élément
- précédent. Notez que ces opérateurs opèrent toujours sur des pointeurs
- et jamais sur l'élément sur lequel pointeur pointe.
-
- "." est similaire à "[]", seulement indexe le pointeur par le nom, ie le
- pointeur doit être un PTR TO <objet>.
-
- "[]" et "." peuvent être concatené à un pointeur p dans n'importe quelle
- séquence, sachant que la valeur précédente retournée doit être du type
- "PTR TO".
-
- On n'a pas besoin d'écrire une définition en entier, comme dans d'autres
- langages, eg si p est un ARRAY OF <objet>, au lieu d'avoir à écrire
- p[index].membre vous pouvez juste écrire p[index], qui donne logiquement
- l'adresse de cet objet. Ca explique alors pourquoi p[].membre est équivalent à
- p.membre, tant que p[] est le même p lorsqu'il pointe sur un objet.
-
- Sémantique par Référence (Reference Semantics):
- Un autre type qui fait du E un peu différent des autres langages et donc
- difficle à comprendre est son penchant pour les sémantiques par références,
- plutôt que des sémantiques par valeur. J'essaye d'argumenter pourquoi c'est
- bien.
-
- Informellement, les sémantiques par référence signifient que les objets
- dans un langage (autre que le type simple comme LONG) sont représentés par
- des pointeurs, alors que les sémantiques par valeur traitent ces objets
- comme valeurs propres. Un exemple de langage qui n'a que des sémantiques
- par valeurs est le BASIC, des exemples de langages qui ont les 2 sont les
- langages de type C/C++ et le Pascal, et des exemples de référence seul
- sont les nouveaux langages Orientés Objets, langages fontionnels comme le
- LISP et bien sûr le E.
-
- Utiliser les sémantiques par référence ne signifie pas occuper des
- pointeurs tout le temps. Vous avez besoin de moins vous en préoccuper dans
- les cas mixtes ou les cas valeurs-uniquement. Particulièrement dans des
- programmes réels, les structures de données sont allouées dynamiquement
- ce qui implique des pointeurs. Le meilleur exemple de cela est le LISP,
- où on programme avec des pointeurs sans s'en apercevoir. En E, on peut
- facilement oublier que STRING est un pointeur, connaissant la facilité
- de copie vers d'autres fonctions ; en C souvent un tas de "&" est nécessaire
- alors qu'en cas équivalent E, aucun ne l'est, et l'équivalent Oberon de
- bla('hallo') ressemble à bla(sys.ADR('hallo')) parce que la chaine ne
- représente pas un pointeur, mais une valeur à part entière...
-
-
-
- +---------------------------------------------------------------+
- | 9. FONCTIONS PREDEFINIES |
- +---------------------------------------------------------------+
-
-
- 9A. fonctions d'entrée - sortie (I/O)
- -------------------------------------
-
-
- WriteF(formatstring,args,...)
-
- affiche une chaine (qui peut contenir des codes de format) vers stdout. De
- zéro à un nombre illimité d'arguments peut être ajoutés. Notez qu'une
- chaine formattée peut être crée dynamiquement, aucune vérification sur le
- nombre d'arguments est (peut être) fait.
- Exemple :
-
- WriteF('salut à tous!\n') /* juste écrit un saut de ligne à */
- /* la fin de la chaine */
-
- WriteF('a = \d \n',a) /* écrit : "a = 123", si a est 123 */
-
- Voir le morceau concernant les chaines, quelque part par ici.
- NOTE : si stdout=NIL, par exemple si votre programme a été lancé du
- Workbench, WriteF() ouvrira une fenêtre de sortie (uniquement sous 2.0),
- et mettra le gestionnaire dans conout et stdout. Cette fenêtre sera
- automatiquement refermée à la sortie du programme, après que l'utilisateur
- aie frappé <return>.
- WriteF() est la seule fonction qui ouvre une fenêtre, donc si vous voulez
- faire des entrées/sorties sur stdout, et pour être sûr que stdout<>NIL,
- faites un WriteF('') comme première instruction de votre programme par
- sécurité.
- Si vous voulez ouvrir une fenêtre console vous même, vous devez faire de
- la sorte de placer le résultat du gestionnaire de fichier (file handle)
- dans les variables stdout et conout, comme ça votre fenêtre sera fermé
- automatiquement à la fin du programme.
- Si vous voulez fermer vous même votre fenêtre, assurez vous de remettre
- conout à NIL, pour signaler au E qu'il n'y a aucune fenêtre console à
- fermer.
-
-
- Out(gestionnaire,car)
- char:=Inp(gestionnaire)
-
- D'une part écrit, d'autre part lit un octet vers un fichier ou sur stdout.
- Si car=-1 alors un EOF est atteint, ou une érreur s'est passée.
-
-
- longueur:=FileLength(nom_chaine)
-
- vous donne la longueur d'un fichier que vous voulez charger, et donc si
- il éxiste ; ou retourne -1 pour une érreur ou si il n'est pas trouvé.
-
-
- ok:=ReadStr(filehandle,estring)
-
- Voir les fonctions de chaines
-
-
- oldout:=SetStdOut(newstdout)
-
- Fixe la variable de sortie standard stdout. C'est l'équivalent de :
-
- oldout:=stdout ; stdout:=newstdout
-
-
- 9B. chaines et fonctions de chaine
- ----------------------------------
-
- Le E possède le type de données STRING. C'est une chaine, appelée à partir de
- maintenant chaine E ('Estring'), qui peut être modifiée et changée en taille,
- à opposer à la chaine normale ('string'), qui sera utilisé pour n'importe
- quelle séquence terminée par un zéro.
- Les chaines E sont rétroactivement compatible avec les chaines, et rien
- d'autres. Alors si un argument demande une chaine normale, on y mettre
- indifféremment l'une des 2 chaines. Si parcontre une chaine E est demandée,
- n'utilisez pas une chaine normale.
- Exemple :
-
- DEF s[80]:STRING, n /* s est une chaine E avec une */
- /* longueur maximum de 80 */
- ReadStr(stdout,s) /* lit un entrée sur la console */
- n:=Val(s,NIL) /* et en sort une valeur */
- ... etc.
-
- Notez que toutes les fonctions de chaine sont gérer de façon à tendre vers
- leur longueur maximum correctement
-
- DEF s[5]:STRING
- StrAdd(s,'ceci est une chaine de 5 caractères',ALL)
-
- s va contenir 'ceci '.
-
-
- s:=String(maxlen)
-
- Une chaine peut donc allouer dynamiquement en mémoire système avec la
- fonction String(), (note: le pointeur retourné par cette fonction doit
- toujours être vérifiée.
-
- DEF s[80]:STRING
-
- est équivalent à :
-
- DEF s
- s:=String(10)
-
-
- bool:=StrCmp(chaine1,chaine2,long)
-
- compare 2 chaines.
-
- long est le nombre d'octet à comparer, ou ALL pour comparer
- toute la longueur.
- Retourne : TRUE ou FALSE
-
-
- StrCopy(chaineE,chaine,long)
-
- copie le chaine vers la chaine E
-
- long : nombre d'octet à copier ou ALL
-
-
- StrAdd(chaineE,chaine,len)
-
- fait comme StrCopy(), à la différence que la chaine est mis à la fin
- de la chaine E (concaténation)
-
-
- long:=StrLen(chaine)
-
- calcule la longueur d'une chaine terminée par un zéro.
-
-
- long:=EstrLen(chaineE)
-
- retourne la longueur d'un chaine E.
-
-
- max:=StrMax(chaineE)
-
- retourne la longueur maximale d'un chaine E
-
-
- RightStr(chaineE1,chainE2,n)
-
- copie les n derniers caractères de la chaine 1 dans la chaine 2
-
-
- MidStr(chaineE1,chaine2,pos,long)
-
- copie un nombre de caractère (long) (tous si long=ALL) à partir de la
- position pos de la chaine 2 sur la chaine 1.
- NOTEZ : dans toutes les fonctions de chaines, le premier caractères à la
- position 0 et non pas 1, comme c'est le cas dans des langages comme le
- BASIC.
-
-
- valeur:=Val(chaine,lecture)
-
- trouve un entier dans une chaine ASCII. Les espaces/tabulations/etc...
- sont sauté, et ainsi les nombres héxadécimaux (123456789abcdef) et
- binaire (01) peuvent être lu de cette manière si ils sont précédés par
- un '$' ou un '%' respectivement. Un '-' signifie un entier négatif.
- Val() retourne le nombre de caractères lu, dans 'lecture', qui doit être
- donné par référence (<-!!!). Si 'lecture' retourne 0 (et la valeur sera
- aussi 0), alors la chaine ne contient pas d'entier, ou la valeur et trop
- grande pour entré dans 32 bits. 'lecture' peut être NIL.
-
- Exemples de chaines qui seront correctement analysées :
- '-12345', '%10101010', ' -$ABcd12'
-
- Ces chaines seront retournés en tant que 'valeur' et dans une variable
- {lu} un zéro :
- '', 'hello!'
-
-
- quelle_pos:=InStr(chaine1,chaine2,pos_départ)
-
- cherche dans la chaine 1, la chaine 2, a partir du caractère pos_départ.
- L'*adresse* a laquelle la chaine 2 a été retrouvé, est retournée, sinon -1.
-
-
- nouv_adr_chaine:=TrimStr(chaine)
-
- retourne l'*adresse* du premier caractère, après avoir enlevé les espaces,
- tabulations, etc...
-
-
- UpperStr(chaineE)
- LowerStr(chaineE)
-
- Transforme les minuscule en masjuscule (respectivement masjuscule en
- minuscule)
- NOTE : ces fonctions modifient le contenu de 'chaine'. On ne peut donc
- utiliser que des chaines E. Cela suppose que vous obteniez l'adresse d'une
- chaine grace à une fonctions de l'Amiga. Vous devez alors faire une copie
- (par StrCopy()) de cette chaine dans une chaine E, puis utiliser ces
- fonctions.
-
-
- ok:=ReadStr(gest_fichier,chaineE)
-
- lit une chaine (se terminant par le code ASCII 10) de n'importe quel
- fichier ou de stdout.
- ok contient -1 si il y a erreur, ou une fin de fichier (EOF) si on est
- à la fin.
- NOTE : le contenu de la chaine lue est toujours valide.
-
-
- SetStr(chainE,nouv_long)
-
- modifie manuellement la longueur d'une chaine E. C'est pratique lorsque
- qu'une fonction autre que les fonctions E, lit une chaine E, et vous
- voulez continuer à utiliser cette variable.
- Par exemple, après avoir utilisé une fonction qui ajoute un zero à la fin
- d'un chaine E, prenez SetStr(ma_chaine,StrLen(ma_chaine)) pour manipuler
- ma_chaine à nouveau.
-
- Pour les fonctions liant les chaines, voir la chapitre 9H
-
-
- 9C. listes et fonctions de liste
- --------------------------------
-
- Les listes sont comme les chaines, à la différence qu'elles consistent en
- LONG, et pas en CHAR.
- Elles peuvent être declarées en globale, locale ou dynamiquement :
-
- DEF maliste[100]:LIST /* local ou global */
- DEF a
- a:=List(10) /* dynamique */
-
- Note que dans le dernier cas, le pointeur 'a' contient NIL
- Tout comme les chaines sont représentées comme constantes dans les
- expressions, les listes ont aussi cette possibilité :
-
- [1,2,3,4]
-
- La valeur d'une telle expression est un pointeur sur une liste initialisée.
- Il en résulte que vous pouvez alors avoir une déclaration dynamique, qui sera
- remplit au moment même de la déclaration :
-
- a:=3
- [1,2,a,4]
-
- De plus, les listes peuvent avoir d'autres types que LONG par défaut :
-
- [1,2,3]:INT
- [65,66,67,0]:CHAR /* équivalent à 'ABC' */
- ['topaz.font',8,0,0]:textattr
- OpenScreenTagList(NIL,[SA_TITLE,'Mon Ecran',TAG_DONE])
-
- Comme le dernier exemple le montre, les listes sont très utiles dans les
- fonctions système : elles sont rétroactivement compatible avec les tableaux
- (ARRAY OF LONG). Les objects peuvent être utilisé n'importe où une fonction
- à besoin d'un pointeur sur une structure, ou un tableau.
- Les fonctions de listes de tags (taglist) et les arguments (vararg) peuvent
- être utilisé de cette façon.
- NOTE : toutes les fonctions de listes travaillent avec des listes de LONG.
- Les listes typées ne sont pratiques que pour construire des structures et des
- expressions.
-
- Comme pour les chaines, une certaine hiérarchie est de rigueur :
- variables de liste -> listes de constantes -> tableau de LONG/pointeur sur LONG
- Quand une fonction a besoin d'un tableau de LONG, vous n'avez qu'à donner une
- liste comme argument, mais quand une fonction demande une variable de liste
- (listvar) ou une liste de constante, alors un tableau de LONG ne marchera pas.
-
- Il est important que vous compreniez la puissance des listes et en particulier
- les listes typées : elles peuvent vous éviter beaucoup soucis lors du codage
- d'une structure de données. Essayez d'utiliser ces listes dans vos propres
- programmes, et regardez en les fonctions dans les programmes exemples. Une fois
- que vous aurez pris le coup, vous ne pourrez vous en passer !
-
- Résumé :
-
- [<élément>,<élément>,... ] liste immédiate (de LONGs, à utiliser
- avec les fonctions de liste)
- [<élément>,<élément>,... ]:<type> listes typées (pour construire des
- structures)
-
- Si <type> est un type simple comme INT ou CHAR, vous n'avez que l'équivalent
- initialisé d'un tableau de <type>.
- Si <type> est le nom d'un objet, vous devez construire cet objet, ou un
- tableau d'<objet>, suivant la longueur de la liste.
- Exemple :
-
- [1,2,3]:INT
-
- vous créez une structure de 6 octets, de 3 fois 16 bits pour être précis. La
- valeur de cette expression est un pointeur sur cette espace mémoire. Il en va
- de même si vous avez un objet :
-
- OBJECT mon_object
- a:LONG, b:CHAR, c:INT
- ENDOBJECT
-
- écrire
-
- [1,2,3]:mon_object
-
- signifiera la création d'un structure en mémoire de 8 octets, avec les 4
- premiers octets étant un LONG de valeur 1. L'octet suivant et un CHAR de
- valeur 2, et les 2 derniers octets un INT (2 octets) de valeur 3. Vous pouvez
- aussi écrire :
-
- [1,2,3,4,5,6,7,8,9]:mon_object
-
- vous créez un tableau de <mon_objet> de taille 3. Notez que de telles listes
- n'ont pas besoin d'être complêtes (3,6,9... éléments), vous pouvez créer
- partiellement des objets avec des listes de n'importe quelle taille.
-
- Une dernière note sur la taille des données :
- Sur l'Amiga, vous remarquerez qu'une structure comme 'mon_objet' a une taille
- de 8, et rempli à 16 pour avoir un mot. Il est certainement peu probable
- qu'un compilateur E pour une architecture 80x86 n'utilisera pas ce
- remplissage et en fera une structure de 7 octets, et qu'un compilateur pour
- une architecture sun-sparc (si je ne me trompe pas) essayera de remplire à 32
- bits, qui fera une structure de 10 ou 12 octets. Certains microprocesseurs
- (rares, pas existants) utilise même les nombres de bits 38:18:9 pour leur type
- LONG:INT:CHAR, au lieu de 32:16:8, comme on le fait. Alors, ne concluez pas
- trop vite en ce qui concerne les objets et les listes, si vous voulez que
- votre code soit portable au maximum, ou n'aie d'effets secondaires.
-
-
- ListCopy(listevar,liste,n)
-
- copie n éléments de la <liste> sur la <listevar>.
- Exemple :
- DEF maliste[10]:LIST
- ListCopy(maliste,[1,2,3,4,5],ALL)
-
-
- ListAdd(listvar,liste,n)
-
- copie n éléments de la <liste> à la fin de <listevar>.
-
-
- ListCmp(list1,list2,n)
-
- compare les 2 listes, ou n éléments d'elles.
-
-
- long:=ListLen(liste)
-
- retourne la longueur de la <liste>.
- Exemple :
- ListLen([a,b,c]) retourne 3
-
-
- max:=ListMax(listevar)
-
- retourne la longueur maximale possible de <listevar>
-
-
- valeur:=ListItem(liste,index)
-
- est l'équivalent de : valeur:=liste[index]
- à la différence que <liste> doit être une constante au lieu d'être un
- pointeur. C'est treès utile dans des cas où vous voulez directement
- utiliser une liste de valeurs :
-
- WriteF(ListItem(['ok!','pas de mem!','pas de fichier!'],erreur))
-
- Cet exemple écrit un message d'erreur en fonction d'<erreur>.
- C'est l'équivalent de :
-
- DEF dummy:PTR TO LONG
- dummy:=['ok!','pas de mem!','pas de fichier!']
- WriteF(dummy[error])
-
-
- SetList(listevar,nouv_long)
-
- fixe manuellement la longueur d'une liste. C'est seulement utile lorsque
- vous lisez utiliser des listes par des fonctions autres que les fonctions
- spécifiques aux listes, et aue vous voulez continuer à l'utiliser comme
- vraie liste.
-
-
- Pour les fonstion de liste qui utilise des expressions cotées '', voir le
- chapitre 11C.
- Pour les fonctions liant les listes, voir le chapitre 9h.
-
-
- 9D. fonctions de support Intuition
- ----------------------------------
-
- wptr:=OpenW(x,y,largeur,hauteur,IDCMP,wdrapeaux,titre,écran,sdrapeaux,gadlist)
-
- crée une fenêtre où :
- - wdrapeaux (wflags) sont des drapeaux pour la mise en forme de la fenêtre
- comme BACKDROP, SIMPLEREFRESH... en général $f
- - sdrapeaux (sflags) est le type d'écran où doit s'ouvrir la fenêtre
- 1 = workbench, 15 = particulier (custom)
- - screen est un pointeur sur l'écran qui doit être valide si sdrapeux = 15
- sinon screen=NIL (0)
- - gadlist pointe sur une structure de liste de gadgets, que vous pouvez
- facilement créer avec la fonction Gadget(), sinon NIL.
-
-
- CloseW(wptr)
-
- ferme la fenêtre de nouveau. La seule différence avec CloseWindow()
- (fonction système) est qu'elle accepte le pointeur null (NIL) et remet
- stdrast à zéro (NIL).
- - wptr est le pointeur donné par OpenW() ou OpenWindow() pour cette
- fenêtre.
-
-
- sptr:=OpenS(largeur,hauteur,profondeur,sdrapeaux,titre)
-
- ouvre un écran pour vous.
- - profondeur est le nombre de plan de bit (bitplanes) (1 à 6, 1 à 8 pour
- les machines AGA),
- - sdrapeaux est le type de résolutions, 0 pour basse résolution, $8000
- pour haute résolution, ajoutez 4 pour l'entrelacement
-
-
- CloseS(sptr)
-
- ferme l'écran. Fonctionne de même facon que CloseW().
- - wptr est le pointeur donné par OpenS() ou OpenScreen() pour cet écran.
-
-
- tampon_suivant:=Gadget(tampon,gadlist,id,drapeaux,x,y,largeur,chaine)
-
- Cette fonction crée une liste de gadgets, qui peuvent être mis dans votre
- fenêtre en les donnant comme argument à OpenW(), ou après l'ouverture
- avec une fonctions Intiotin comme AddGlist().
- - tampon (buffer) est souvent un tableaux de taille GADGETSIZE octets
- pour sauver toutes les structures associées à un gadget,
- - id est le n'importe quelle nombre vous permettent de vous rappeler de
- quel gadget il s'agit lorsqu'il est pressé,
- - drapeaux : 0 = gadget normal
- 1 = gadget booléen (interrupteur)
- 3 = gadget booléen pressé
- - largeur est la largeur en pixel. Il doit être suffisament grand pour
- contenir la chaine qui est auto-centrée,
- - gadlist doit être NIL pour le premier gadget, puis glistvar pour le
- tampon suivant, comme ça le E poura faire le lien entre les gadgets.
- La fonction retourne un pointeur sur le tampon suivant
- (=tampon+GADGETSIZE).
- Exemple pour 3 gadgets :
-
- CONST MAXGADGETS=GADGETSIZE*3
-
- DEF tampon[MAXGADGETS]:ARRAY, suivant, wptr
-
- suivant:=Gadget(tampon,NIL,1,0,10,20,80,'bla') /* le premier gadget */
- suivant:=Gadget(suivant,tampon,... )
- suivant:=Gadget(suivant,tampon,... ) /* n'importe lequel */
- /* lie les 2 premiers */
-
- wptr:=OpenW( ...,buf)
-
- Regardez les exemples comme SuperVisor.e pour une exemple parlant.
-
-
- code:=Mouse()
-
- donne l'état actuel des 2 ou 3 boutons de la souris ;
- 1 = gauche, 2 = droit, 4 = centre
- Si par exemple code=3 alors les boutons gauches est droit sont pressés.
- NOTE : ce n'est pas une réelle fonction Intuition. Si vous voulez connaitre
- les évènements de la souris de manière propre, regardez dans la structure
- intuimessage que votre fenêtre recoit.
- C'est la seule fonction du E qui contrôle le hardware, et n'est utile aue
- dans des programmes de style démos.
-
-
- x:=MouseX(fenêtre)
- y:=MouseY(fenêtre)
-
- vous permet de lire les coordonnées de la souris.
- - fenêtre est le pointeur sur la fenêtre par rapport à laquelle les
- coordonnées seront relatives
-
-
- classe:=WaitIMessage(fenêtre)
-
- Cette fonction rend plus facile l'attente d'un évènement dans une fenêtre.
- Elle attend simplement qu'un message intuition arrive, et retourne la
- classe de cet évènement. Elle mets les autres variables comme le code
- comme variables globales privées, afin d'y accéder grace aux fonctions
- ci-dessous.
- WaitImessages est l'équivalent du code suivant :
-
- PROC waitimessage(win:PTR TO window)
- DEF port,mes:PTR TO intuimessage,class,code,qual,iaddr
- port:=win.userport
- IF (mes:=GetMsg(port))=NIL
- REPEAT
- WaitPort(port)
- UNTIL (mes:=GetMsg(port))<>NIL
- ENDIF
- class:=mes.class
- code:=mes.code /* sauvé en interne */
- qual:=mes.qualifier
- iaddr:=mes.iaddress
- ReplyMsg(mes)
- ENDPROC class
-
- comme vous le voyez, la fonction prend exactement un message, et n'oubliez
- pas qu'il peut arriver plusieurs messages dans un évènement, si appelé
- plus d'une fois.
- Par exemple, ovus ouvrez une fenêtre qui affiche quelque chose et attend
- que l'on presse sur le gqdget de fermeture de l'écran (vous avez spécifiez
- IDCMP_CLOSEWINDOW) à l'ouverture de la fenêtre) :
-
- WaitIMessage(ma_fenêtre)
-
- ou vous avez un programme qui attend plusieurs types d'évènement, les gére
- dans une boucle, et sort avec le gadget de fermeture :
-
- WHILE (class:=WaitIMessage(win))<>IDCMP_CLOSEWINDOW
- /* gestion de classes */
- ENDWHILE
-
-
- code:=MsgCode()
- qual:=MsgQualifier()
- iaddr:=MsgIaddr()
-
- Ces fonctions vous donneront les variables globales privées mentionnées
- plus haut. Les valeurs retournnées sont définies d'après l'appel le plus
- récent de WaitIntuiMessage().
- Exemple :
-
- IF class:=IDCMP_GADGETUP
- mon_gadget:=MsgIaddr()
- IF mon_gadget.userdata=1 THEN /* ... on a pressé le gadget #1 */
- ENDIF
-
-
- 9E. fonctions de support graphique
- ----------------------------------
-
- Toutes les fonctions de support graphique qui n'implique pas directement
- un rastport, utilise la variable système 'stdrast'. Elle est automatiquement
- définie par le dernier appel de OpenW ou OpenS(), et remis à NIL avec CloseW()
- et CloseS.
- Appeler ces fonctions avec stdrast égal à NIL est légal. stdrast peut être
- manuellement modifié par SetStdRast() ou stdrast:=mon_rastport.
-
-
- Plot(x,y,couleur)
-
- dessine un point sur l'écran/fenêtre dans la couleur voulue.
- - couleur = 0 à 31, 0 à 255 pour les machines AGA.
-
-
- Line(x1,y1,x2,y2,colour)
-
- trace une ligne
-
-
- Box(x1,y1,x2,y2,colour)
-
- trace une boite
-
-
- Colour(avant,fond)
-
- fixe les couleurs des fonctions graphiques qui ne prennent pas de couleur
- comme argument. C'est le *registre* de couleur qui est demandé, pas la
- *valeur*.
- NOTE : les fonctions qui ont un argument de 'couleur', modifie le Apen du
- stdrast.
-
-
- TextF(x,y,chaine_formattée,args,...)
-
- tout comme la fonction WriteF(), mais uniquement à (x,y) sur votre
- stdrast, au lieu de stdout.
- Voir WriteF() et les chaines
-
-
- anc_rast:=SetStdRast(nouv_rast)
-
- change le rastport de sortie des fonctions graphiques du E
-
-
- SetTopaz(taille)
-
- fixe la police de caractères (font) du rastport 'stdrast'. Assurez vous
- que certaine police système de l'utilisateur ne modifieront pas votre
- mise en page.
- - taille = 8 ou 9
-
-
- 9F. fonctions de support du système
- -----------------------------------
-
- bool:=KickVersion(vers)
-
- retourne TRUE si le Kickstart de la machine est égal ou supérieur à
- <vers>, sinon FALSE
-
-
- mem:=New(n)
-
- créé dynamiquement un tableau (ou un espace mémoire, si vous voulez) de
- <n> octets. La différence avec AllocMem() est que l'appel se fait
- automatiquement avec un dreapeau de $10000 et que vous n'avez pas à
- appeler Dispose(), car lié à une liste mémoire qui est automatiquement
- désallouée à la sortie du programme.
-
-
- Dispose(mem)
-
- gèle n'importe quelle <mem> alloué par New(). Vous ne devez utiliser cette
- fonction que si vous voulez libérer explicitement de la mémoire _pendant_
- que la programme tourne, tout comme cela se fait à la sortie de celui-ci.
-
-
- CleanUp(valeur_retournée)
-
- sort du programme à n'importe quel moment. Il remplace la fonction DOS
- Exit() : n'utilisez jamais celui-là ! plutôt CleanUp(), qui permet de
- désallouer la mémoire, de fermer correctement les bibliothèques, etc.
- La <valeur_retournée> est donnée au DOS comme code de retour (returncode).
-
-
- espace:=FreeStack()
-
- retourne l'espace libre de la pile. Cela doit toujours être 1000 ou plus.
- Voir le chapitre 'implémentation' sur comment le E organise sa pile.
- Si vous n'avez pas de trop grosses récursions, vous n'avez pas à vous en
- faire quant à cet espace libre.
-
-
- bool:=CtrlC()
-
- retourne TRUE si Ctrl-C est pressé depuis la dernière fois, sinon FALSE.
- Cela ne marche que pour les programmes lancés via le shell (des programmes
- CLI).
-
-
- Exemple montrant comment les 3 dernière fonctions peuvent être utilisées :
-
- /* calcule le factoriel de l'argument de la ligne de commande */
-
- OPT STACK=100000
-
- PROC main()
- DEF num,r
- num:=Val(arg,{r})
- IF r=0
- WriteF('mauvais args.\n')
- ELSE
- WriteF('résultat: \d\n',fac(num))
- ENDPROC
- ENDPROC
-
- PROC fac(n)
- DEF r
- IF FreeStack()<1000 OR CtrlC() THEN CleanUp(5) /* vérif suppl */
- IF n=1 THEN r:=1 ELSE r:=fac(n-1)*n
- ENDPROC r
-
- Bien sûr, cette récursion marchera difficilement avec peu de pile, et quand il
- marche, il est stoppé si vite par FreeStack() que vous n'aurez pas le temps
- de presser Ctrl-C, mais l'idée est là.
- Une définition de fac(n) comme suit est moins sûre :
-
- PROC fac(n) RETURN IF n=1 THEN 1 ELSE fac(n-1)*n
-
-
- 9G. mathématiques et autres fonctions
- -------------------------------------
-
- a:=And(b,c)
- a:=Or(b,c)
- a:=Not(b)
- a:=Eor(b,c)
-
- Ceux-ci marchent comme les opérations usuelles, aussi bien booléennes
- qu'arithmétiques.
- Notez que pour And() et Or(), un opérateur existe.
-
-
- a:=Mul(b,c)
- a:=Div(a,b)
-
- réalise les mêmes opérations que les opérateurs '*' et '/', mais
- maintenant en vrai 32 bits. Pour des raisons de rapidité, les opérations
- normale sont faites en 16 bits * 16 bits = 32 bits et 32 bits / 16 bits
- = 16 bits. C'est suffisent pour quasiment tous les calculs, et quand ce
- n'est pas le cas, utilisez Mul() et Div().
- NOTE : pour Div(), a est divisé par b, pas l'inverse.
-
-
- bool:=Odd(x)
- bool:=Even(x)
-
- retourne TRUE ou FALSE si x est impaire (Odd) ou paire (Even)
-
-
- num:=Rnd(max)
- seuil:=RndQ(seuil)
-
- Rnd() donne un nombre au 'hasard' à partir d'un seuil allant de 0 à max-1.
- Par exemple, Rnd(1000) retourne un entier entre 0 et 999.
- Pour initialiser le seuil interne, appelez Rnd() avec un nombre négatif.
- la valeur absolue de cette valeur sera le seuil initial.
-
- RndQ() calcul un nombre au 'hasard' plus vite (Quicker) que Rnd(), mais
- retourne un nombre sur 32 bits. Utilisez le résultat comme seuil pour le
- prochain appel, et pour seuil de départ, utilisez un grande valeur, comme
- $A6F87EC1.
-
-
- valeur_abs:=Abs(valeur)
-
- calcule la valeur absolue.
-
-
- a:=Mod(b,c)
-
- divise b (32bits) par c(16bits) et retourne le modulo a (16bits)
-
-
- x:=Shl(y,n)
- x:=Shr(y,n)
-
- déplace y de n bits vers la gauche (Shl) ou vers la droite (Shr)
-
-
- a:=Long(adr)
- a:=Int(adr)
- a:=Char(adr)
-
- lit (peek) la mémoire à l'adresse <adr>, et retourne la valeur trouvée.
- Ces fonctions travaillent avec respectivement des valeurs de 32, 16 et 8
- bits. Notez que le compilateur ne vérifie pas si l'<adr> est valide. Ces
- fonctions sont implementées en E pour les cas où écrire ou lire la mémoire
- par des pointeur (PTR TO <type>) demanderait une programmation complexe,
- voire moins bonne.
- Vous n'êtes pas encouragé à utiliser ces fonctions.
-
-
- PutLong(adr,a)
- PutInt(adr,a)
- PutChar(adr,a)
-
- écrit (poke) la valeur <a> à l'adresse <adr> en mémoire.
- Voir : Long()
-
-
- 9H. fonctions liants les chaines, les listes
- --------------------------------------------
-
- Le E propose un ensemble de fonctions qui permettent la création de listes
- liées (linked) avec les types de données STRING et LIST, ou chaines et
- listes qui sont créés avec String() et List(). Comme vous devez le savoir
- maintenant, les chaines et les listes sont des pointeurs sur leurs données
- respectives, et ont des champs suppléméntaires d'offsets négatifs décrivant
- leur longueur actuelle et leur longueur maximale. Ces offsets dont PRIVÉs.
- Ajouté à ces 2 champs, n'importe quel type de donnée complexe, a un champ
- 'next' (suivant), égal à NIL par défaut, qui peut servir à construire une
- liste de chaines liées (linked), par exemple.
- Dans la suite, j'utiliserai le terme 'complexe' pour signifier un pointeur
- sur une chaine ou une liste, et 'queue' (tail) pour signifier un tel pointeur
- ou un qui a déja d'autres chaines liées à lui. 'queue' peut alors être un
- pointeur NIL, ce qui signifie la fin de la liste.
-
-
- complexe:=Link(complexe,queue)
-
- mets la valeur <queue> dans le prochain champ de <complexe>. Retourne de
- nouveau <complexe>.
- Exemple :
-
- DEF s[10]:STRING, t[10]:STRING
- Link(s,t)
-
- crée une liste liée comme : s --> t --> NIL
-
-
- queue:=Next(complexe)
-
- lit le champ suivant de la variable <complexe>. Cela peut être bien sûr
- NIL, ou une liste liées entière. Appeler Next(NIL) donnera NIL, il est
- donc prudent d'appeler Next() si vous n'êtes pas sûr que vous êtes à la
- fin de la liste liée.
-
-
- queue:=Forward(complexe,n)
-
- pareil que Next(), seulement avance de n liens, au lieu d'un seul, donc :
-
- Next(c) = Forward(c,1)
-
- Vous pouvez sans crainte appeler Forward() avec n trop grand, la fonction
- s'arrètera si elle rencontre NIL pendant la recherche de liens, et
- retournera NIL.
-
-
- DisposeLink(complexe)
-
- fait de même que Dispose(), avec 2 différences : la fonction ne marche
- qu'avec les chaines et listes allouées par String() et List(), et
- désallouera automatiquementla queue du complexe aussi.
- Notez que de grandes listes liées contenant des chaines alouées par
- String(), tout comme celles allouée localement ou globalement avec
- STRING, doivent être désallouée de cette façon.
-
- Pour un bon exemple de comment des listes liées de chaines peuvent être
- utilisé, voir le programme 'D.e'
-
-
- 9I. cellule lisp et fonctions cellulaires
- -----------------------------------------
-
- a) Définition :
- ----------
-
- Ouaip. C'est vrai. Vous pensiez que le LISP c'était chouette, ben, essayez le
- E maintenant. [Ou bien : l'histoire de pourquoi le E est un meilleur LISP que
- le LISP même :-)]
-
- A partir de la v3, le E possède les type de donnée cellulaire ('cell
- datatype'), quasi identique aux cellules du langage LISP. D'un point de vue
- technique, E a:
-
- `Conservative Mark and Sweep Garbage-Collected Lisp-Cells'
-
- Simplement, cela lui permet d'être capable d'allouer des cellules LISP qui
- sont des paires de 2 valeurs.
-
- x:=<a,b>
-
- ce qui est mieux que NEW [a,b]:LONG, seulement maintenant le E désallouera
- les 8 octets en question lui-même lorsqu'il aura besoin de mémoire et qu'aucun
- pointeur n'y pointe. En pratique, cela signifie que vous pouvez avoir des
- fonctions qui crée des cellules tampons sans vous soucier de les libérer. Et
- tout programmeur en LISP sera capable de vous expliquer qu'avec des cellules,
- vous pouvez construire n'importe quelle structure de donnée (et en
- particulier des arbres et des listes).
- [Note: ce texte n'explique pas comment faire pour utiliser complètement les
- cellules, car des douzaines de livres sur le LISP on été écrit à ce propos].
-
- Choisir des valeurs peut être facilement fait grace à Car(x) et Cdr(x), 2
- fonctions LISP qui prenne la tête ('head') et la queue ('tail') (premier et
- second) élément de la cellule. Si x est un PTR TO LONG, même x[0] et x[1] sont
- permis.
-
- On peut aussi écrire des listes de cellules
-
- <a,b,c>
-
- (notez les virgules) étant le raccourcit de
-
- <a:<b:<c:NIL>>>
-
- Une alternative à Car/Cdr est l'unification E:
-
- x <=> <a,b:c>
- a+b+c
-
- au lieu de:
-
- Car(x)+Car(Cdr(x))+Cdr(Cdr(x))
-
- L'unification cellulaire du LISP ressemble à l'unification des listes E.
- (voir 4L)
- Par exemple:
-
- x <=> <1,2|a>
-
- est équivalent à:
-
- IF Car(x)=1
- IF Car(Cdr(x))=2
- a:=Cdr(Cdr(x))
- ...
-
-
- Une valeur nulle LISP est possible "<>", qui est égal à NIL et 0.
-
- Certaines fonctions sont possibles (notez que Cons() n'est _seulement_ possible
- avec <...>).
-
- b) Fonctions :
- ---------
-
- h:=Car(c) t:=Cdr(c)
-
- fixe la tête ('head') et la queue ('tail') de la cellule c
-
- bool:=Cell(c)
-
- donne l'état de c, si elle pointe ou non sur une cellule, donc
- Cell(<1>)=TRUE, et Cell(3.14)=FALSE. Ce n'est pas une fonction rapide.
-
- n:=FreeCells()
-
- retourne la quantité de cellule libre possible. C'est une fonction très
- lente. Il ne devrait y avoir besoin d'appeler cette fonction, sinon par
- curiosité.
-
- SetChunkSize(k)
-
- Fixe la taille des chunks pour allouer k kilooctets pour les cellules. Le
- défaut est de 128 Ko. Cett fiction nepeut être appeler qu'une seule fois,
- et seulement avant que la première allocation soit faites. Après, la
- fonction n'a aucun effet.
-
- En général; prenez un bon bouquin sur le LISP pour mieux comprendre comment
- utiliser les cellules.
-
- On peut écrire n'importez quelle fonctions LISP en E, avec éxactement la même
- fonctionnalité:
-
- PROC append(x,y) IS IF x THEN <Car(x)|append(Cdr(x),y)> ELSE y
- PROC nrev(x) IS IF x THEN append(nrev(Cdr(x)),<Car(x)>) ELSE NIL
- PROC sum(x) IS IF x THEN Car(x)+sum(Cdr(x)) ELSE 0
-
- Utiliser une implementation destructive pour des fonctions comment celles-là
- est aussi possible.
-
- c) De la technique :
- ---------------
-
- Le 'garbage collector' implémente 'a conservative mark and sweep algorithm'
- qui a été testé pour être 5 à 25 fois plus rapide que plusieurs implémentations
- de langage logique et fonctionnel sur l'Amiga. Conservative signifie qu'en cas
- de doute, le GC (Garbage Collector) ne désallouera pas une cellule. Ceci est
- nécessaire à cause dy langage sans type tel que le E, le GC peut facilement
- recontrer une valeur qui n'est pas un pointeur valide etc.
-
- Le GC alloue de gros chunks (128Ko par défaut), dans lesquels il alloue des
- cellules. Par manque de cellule, il cherchera de la place en regardant la pile
- et les registres de pointeurs dans l'espace cellulaire, et récursivement les
- marquera. Après quoi, toutes les cellules non marquées sont réutilisées, et si
- le gain en cellule est petit, un nouveau chunk sera alloué.
-
- Intéraction avec d'autres valeur du E:
- - sauver d'autres valeurs dans les celluels n'est pas un problême. Objets,
- chaines, flottants, n'importe quoi peut être mis dans une cellule sans
- trop importuner le GC ;
- - sauver des cellules dans d'autres valeurs, par exemple un pointeur sur une
- cellule dans un objet dynamique, est problematic, car le GC ne sera pas
- capable de le trouver là. Une solution sera trouvée. Malgré tout je pense
- que cela n'arrivera que très rarement.
- Des pointeurs sur des cellules peuvent sauvé en toute sécurité dans des
- variables globales et locales, même des registres, et n'importe quelle
- structure de donnée. [et plus important dans d'autres cellules!]
-
- Caveats:
- - Le GC ne peut collecter des cellules qui ont une liste de Car >1000, ie
- <<<NIL:a>:b>:c>, mais de 100 entrées au lieu de 3 ici. Cela arrivera
- difficilement car leslistes comme celle-la sont toujours formés comme
- des listes de Cdr, que le GC peut agrandir à l'infinie.
- - le code assembleur en ligne ne doit jamais mettre dans la pile de choses
- qui se sont pas alignés sur des LONGs. Ceci était déja valable pour la
- version 2.1b, mais maintenant c'est plus qu'essentiel.
-
- Il y a une différence en taille de chunk entre l'espace et le temps.
- Allouer de petits chunks est bien tant que vous ne dépensez pas beaucoup de
- mémoire, malgré tout, lorrs de la collection (garbage collecting), l'effort
- de chaque pointeur pour tracer est proportionnel à l'espace. Pour cela :
- - si la vitesse est le plus important, mettez la taille des chunks de telle
- façon qu'un seule espace est nécessaire. Si l'utilisation maximale d'une
- cellule est de 50Ko, un chunk de 100 a 150 Ko donnera un performance
- maximale ;
- - si l'utilisation dela mémoire est le plus important, dans l'exemple
- ci-dessus, des chunks de 20Ko ou 30Ko sera optimal pour la mémoire.
-
- En général, calculer le temps d''utilisation maximal de votre algorythme
- cellulaire avec différentes tailles pour voir quelle valeur est la
- meilleure.
-
-
-
- +---------------------------------------------------------------+
- | 10. FONCTIONS DE BIBLIOTHEQUES ET MODULES |
- +---------------------------------------------------------------+
-
-
- 10A. appels de bibliothèque prédéfinis (built-in)
- -------------------------------------------------
-
- Comme vous l'avez remarqué dans les sections précédentes, le morceau de code
- lié (linked) automatiquement au début de votre source, appelé 'code
- d'initialisation', ouvre toujours les 4 bibliothèques Intuition, Dos, Graphics,
- Mathffp, et à cause de ça, le compilateur possède tous les appels des 5
- bibliothèques (avec l'exec) (il y en a une petite centaine).
- Ces appels sont valables jusqu'au workbench 2.04. Ceux du système 3.0 devrait
- être inclus dans la prochaine version d'Amiga E.
- Exemple, pour appeler la fonction Open(), de la bibliothèque Dos, écrivez :
-
- gestion:=Open('mon_fichier',OLDFILE)
-
- ou AddDisplayInfo() de la bibliothèques graphics :
-
- AddDisplayInfo(mes_info)
-
- Aussi simple que ça !
-
-
- 10B. interfacer le système Amiga avec les modules v39
- -----------------------------------------------------
-
- Pour utiliser d'autres bibliothèques que les 5 décrites dans la section
- précédente, vous avez besoin de modules. Aussi, si vous voulez utiliser des
- objet (OBJECT) ou des constantes (CONST) d'includes utilisé en C ou en
- Assembleur, vous vew besoin de modules.
- Les modules sont des fichiers binaires qui peuvent inclure des définitions de
- constantes, d'objets, de bibliothèques et de fonction. L'avantage que les
- modules soient compilées, par rapport à des fichiers ASCII, est qu'ils n'ont
- pas besoin d'être recompilé encore et encore, chaque fois que votre programme
- est compilé. Le désavantage est qu'ils ne peuvent pas être facilement être
- visualisés ; ils ont besoin d'utilitaires comme ShowModule (voir 17A) pour les
- rendre visible.
- Les modules contenant les définitions de bibliothèque (les appels) sont dans
- le répertoire racine de emodules: (le répertoire de module de la distribution)
- Les définitions des constantes/objets sont dans les sous-répertoires,
- structurés comme les modules originaux de Commodore.
-
- syntaxe: MODULE <nom_module>,...
-
- charge un module. Utiliser les modules vous permet d'utiliser des bibliothèques
- et des fonctions alors inconnus du compilateur (et du système).
-
- Exemple : un raccourcit du programme 'source/examples/asldemo.e' qui utilise
- des modules pour afficher une boites de requête de fichier (filerequester), de
- la bibliothèque Asl.library du système 2.0.
-
- MODULE 'Asl', 'libraries/Asl'
-
- PROC main()
- DEF req:PTR TO filerequestr
- IF aslbase:=OpenLibrary('asl.library',37)
- IF req:=AllocFileRequest()
- IF RequestFile(req) THEN WriteF('File: "\s" in "\s"\n',
- req.file,req.dir)
- FreeFileRequest(req)
- ENDIF
- CloseLibrary(aslbase)
- ENDIF
- ENDPROC
-
-
- Du module 'asl', le compilateur prend les définitions des fonctions de l'asl
- comme RequestFile(), et la variable globale 'aslbase', qui doit seulement être
- initialisée par le programmeur.
- Du module 'libraries/asl', il prend la définition de l'objet de la boite de
- requête de fichier (filerequester), qu'on utilise pour lire le fichier choisit
- par l'utilisateur.
- Alors, ce n'était pas trop dur de programmer une boite de requête en E ?
-
-
- 10C. compiler ses propres modules
- ---------------------------------
-
- Avec la v3, vous pouvez réunir tous les PROCs, CONSTs, OBJECTs et quelques
- variables globales que vous sentez qu'ils appartiennent au même source,
- écrivez "OPT MODULE" pour signaler à EC qu'il doit être un module, et doit
- être compiler en fichier .m pour être utilisé dans un programme principal,
- tout comme vous le faisiez avec les 'vieux' modules.
-
- Par défaut, tous les éléments d'un module sont PRIVÉS, ie non accessible
- au code qui importe le fichier .m. Pour montrer les éléments que vous voulez
- être visible dans le module, écrivez EXPORT devant:
-
- EXPORT ENUM TEST,UN,DEUX,TROIS,QUATRE
-
- EXPORT DEF variable_globale_importante, bla:PTR TO x
-
- EXPORT OBJECT x
- suivant,index, terme
- ENDOBJECT
-
- EXPORT PROC truc()
- /* n'importe quoi */
- ENDPROC
-
- "EXPORT" est utile pour faire la distinction entre privé et public,
- spécialement quand toutes les fonctions d'un OBJEcT peuvent être accessible
- par PROCs, vous pouvez avoir envie de garder des OBJEcTs privé comme méthode
- effective pour chacher des données (data hiding). Plus sur ce sujet, voir 14C.
-
- Si dans un module _tous_ les éléments ont besoin d'être exporté (par exemple
- un avec uniquement des constantes), un 'OPT EXPORT' exportera tout, sans
- avoir besoin de les déclarer individuellement par EXPORT.
-
- Les variables globales demande une attention particulière:
- - essayez d'éviter un tas de variables globales. Cela ajoute du désordre à
- votre projet et le rend sensible aux erreurs ;
- - les globales dans un module ne peuvent pas être initialisée directement
- dans la déclaration DEF (la raison est expliqué plus bas). Par exemple:
- DEF a pas DEF a=1
- DEF a:PTR TO x pas DEF a[10]:ARRAY OF x
- - les globales dans un module qui ne sont pas exportées fonctionnent comme
- des locales pour le module, ie ils n'y aura pas de conflit avec les
- globales d'autres modules. Celles qui _sont_ exportées sont combinés avec
- les autres, ie si dans le programme principale et les autres modules
- une variable avec le même nom est utilisée, ce sera une et même variable.
- C'est pourquoi on peut écrire DEF a[10]:ARRAY OF x dans le programme
- principale, et EXPORT DEF a:PTR TO x dans le module, pour partager le
- tableau. Aussi, si les 2 utilisent par exemple 'gadtools.m', uniquement
- un des 2 a besoin d'initialiser 'gadtoolsbase' pour les 2 pour pouvoir
- faire un appel de la bibliothèque. Si vous ne voulez pas que la base de
- la bibliothèque soit partagé (ie vous voulez avoir une base de
- bibliothèque locale et privée), simplement redéclarez le dans un DEF
- qui n'est pas EXPORTé. Si vous exportez une variable d'une manière
- générale d'un module, donnez lui un chouette petit nom unique.
- - utiliser des globales dans des modules qui propose des types de données
- générales demende un peu d'attention. Le module peut être utilisé par
- plus d'un autre module, dans lesquels il peut être difficile de
- connaitre à qui appartient telles ou telles variables. Faites bien
- attention à cela.
-
- Utiliser des modules dans des modules.
- Cela demande (encore) un peu d'attention. Soi le module (B) que vous
- incluez dans votre propre module (A) ne déclare que des CONSTs,
- bibliothèques (LIBRARY) et OBJEcTs (sans code) rien de spéciale ne se
- passe, mais si B inclue des PROCs, alors il est évident que ce code devra
- être linké plus tard. Ainsi si un programme principal utilise A, B devra
- être présent pour le compilation. Le fait que A aie besoin de B, est sauvé
- dans A, et peut être visualisé avec ShowModule. Ce type d'utilisation peut
- grossir et donner un arbre de dépendance, ce qui a pour résultat suivant,
- si vous utilisez un module dans votre programme, un tas d'autre sont
- automatiquement linké à lui. Ainsi, le système de module E garde
- automatiquement des traces des dépendances alors que d'autres langages ont
- besoin d'un makefile. EC permet aussi des inclusions circulaires, et
- charge/linke des modules au plus une fois (ie, ne linke pas des modules
- inutilisés).
-
-
- Essayez le nouveau ShowModule (voir 17A) pour voir ce que EC met dans les
- modules.
-
- Inclure des modules d'autres répertoires.
- Par défaut, un nom de module est préfixé par 'emodules:' pour obtenir le
- fichier actuel. Maintenant vous pouvez préfixer le nom avec un '*' pour
- donner le répertoire où le source se trouve, donc:
-
- MODULE 'chose', '*chose'
-
- Si cette déclaration était dans le source 'WORK:E/truc.e', ces 2 modules
- seraient 'emodules:chose.m' et 'WORK:E/chose.m'.
-
- C'est le voie normale d'inclure des parties de votre application dans d'autres
- parties. Si vous écrivez des modules que vous utilisez dans plusieurs
- programmes, il seraient pratique de les archiver dans une hiérarchie de
- modules E, et la place pour ça est le répertoire 'emodules/other/'.
-
-
-
- 10D. le module cache
- --------------------
- (voir 17D, ShowCache/FlushCache à ce propos).
-
-
-
- +---------------------------------------------------------------+
- | 11. EXPRESSIONS COTÉES |
- +---------------------------------------------------------------+
-
-
- 11A. les cotes (quotes) et analyse (scope)
- ------------------------------------------
-
- Les expressions cotées commence avec une apostrophe inverse `. La valeur
- d'une expressions cotées n'est pas le résultats d'un calcul d'une expression,
- mais l'adresse du code. Le résultat peut être passé à une variable normale, ou
- comme argument de certaines fonctions.
- Exemple:
-
- mafonc:=`x*x*x
-
- mafonc est maintenant un pointeur sur une fonction qui calcule x^3 quand elle
- est évaluée. Ces pointeurs de fonctions sont très différents des procédures
- normales et ne doivent jamais être mélangées. Les plus grandes différences
- sont qu'une expression cotée est une simple expression, et donc, ne peut pas
- avoir sa propre variable locale. Dans notre exemple, 'x' est juste une variable
- locale ou globale. C'est là que nous devons être prudent :
- Si on évalue mafonc plus tard dans la même procédure, 'x' doit être local,
- mais si mafonc est donné comme paramètre à une autre procédure, et puis
- évauluée, 'x' doit être global. Il n'y a aucune vérification du compilateur.
-
-
- 11B. Eval(fonc)
- ---------------
-
- évalue simplement une expressions cotées (exp = Eval(`exp)).
-
- NOTE : parce que le E est un langage peu typé, écrire accidentellement
- 'Eval(x*x)' au lieu de 'Eval(`x*x) ne sera pas remarqué par le compilateur,
- et vous donnera beaucoup de problême : la valeur de x*x sera utilisé comme
- pointeur à coder.
-
- Pour comprendre pourquoi les 'expressions cotées' sont un atout puissant,
- pensez au cas suivant :
- - if vous voulez réaliser un ensemble d'actions suivant un ensemble de
- variables, vous devez normalement écrire une fonction, et l'appeler avec
- différents arguments. Mais que ce passe-t-il si l'élément que vous voulez
- passer tout un code ? Dans les langages traditionnels, c'est impossible.
- Pas en E.
- Exemple : supposons quez vous voulez écrire un programme qui compte le temps
- éxécution de différentes expressions. En E, on écrire :
-
- PROC timing(fonc,titre)
- /* faites plein de chose pour définir le temps */
- Eval(fonc)
- /* et le reste */
- WriteF('temps mesuré pour \s est \d\n',titre,t)
- ENDPROC
-
- et appelez le avec :
-
- timing(`x*x*x,'multiplication')
- timing(`sizycalc(),'gros calcul')
-
-
- dans d'autres langages, vous devez avoir des copies de 'timing()' pour
- chaque appel, ou vous devez mettre chaque expression dans une fonction
- séparé.
-
- Un autre exemple simple : pensez à ce que vous pouvez faire avec des
- structures de données (listes) rempli de code non évalué :
-
- tracefonc:=[`Plot(x,y,c),`Line(x,y,x+10,y+10,c),`Box(x,y,x+20,y+20,c)]
-
- Notez que l'idée de fonctions comme des variables/valeurs normales n'est pas
- nouvelles en E. Les expressions cotées viennent litéralement du LISP, qui
- possède la fonction encore plus puissante appelé Lambda, qui peut être donnée
- comme arguments à des fonctions ; les expressions cotées de E peuvent aussi
- être vu comme des fonctions Lambda sans paramêtre (ou seulement avec des
- paramêtres globals).
-
-
- 11C. built-in functions
- ----------------------
-
- MapList(varadr,liste,listevar,fonc)
-
- calcule la fonction sur tous les éléments de <liste>, et retourne tous les
- résultats dans <listevar>. <func> doit être une expressions cotées (voir
- plus haut). <varadr> est donné par référence.
- Exemple :
-
- MapList({x},[1,2,3,4,5],r,`x*x) r est alors : [1,4,9,16,25]
-
-
- ForAll(varadr,list,func)
-
- retourne TRUE si tous les éléments de la liste sont évalués par la
- fonction comme vrais, sinon FALSE. Peut être aussi utilisé pour réaliser
- une certaine fonction sur tous les éléments d'une liste :
-
- ForAll({x},['un','deux','trois'],`WriteF('exemple: \s\n',x))
-
-
- Exists(varadr,list,func)
-
- Comme pour ForAll(), mais retourne TRUE si la fonction évalue au moins
- un élément de vrai (<>0).
- Notez que ForAll() évalue toujours tous les éléments, mais pas forcément
- Exist().
-
- Exemple de comment utiliser ces fonctions en pratique :
- on alloue differentes tailles en mémoire en une définition, les vérifie en
- une seule fois, et les libère toutes, mais uniquement celles qui ont été
- alouée. (v37+) :
-
- PROC main()
- LOCAL mem[4]:LIST,x
- MapList({x},[200,80,10,2500],mem,`AllocVec(x,0)) /* alloue quelques */
- IF ForAll({x},mem,`x) /* suxxes ? */
- WriteF('Yes!\n')
- ELSE
- WriteF('No!\n')
- ENDIF
- ForAll({x},mem,`IF x THEN FreeVec(x) ELSE NOP) /* libère seulement */
- /* ceux qui sont <>NIL */
- ENDPROC
-
-
- Notez l'abscence d'itération dans ce code. Essayez de reécrire cet exemple
- dans autre langage pourquoi c'est si spécial.
-
-
-
- +---------------------------------------------------------------+
- | 12. SUPPORT DES NOMBRES FLOTTANTS |
- +---------------------------------------------------------------+
-
-
- 12A. utiliser les flottants et les opérateurs flottants
- -------------------------------------------------------
-
- Surpasser les opérateurs standard + * etc, avec leurs équivalents flottants
- est possible à partir du système 2.0 de l'Amiga E, mais j'ai enlevé la partie
- principale de la documentation les concernant, car le concept flottant en E
- changera avec les versions supérieures : ces versions vous permettra du code
- inline pour 68881 pour des routines FFP, et de façon transparente.
-
- Si vous voulez réellement utiliser les flottants avec la version 2.1b, vous
- êtes prié d'utiliser les routines prédéfinies SpXxx() de la bibliothèque
- mathffp.library.
- Exemple:
-
- x:=SpMul(y,0.013483)
-
- Attention quand la prochaine version sortira, votre source devra être modifié
- (en mieux !).
-
-
- 12B. expressions flottantes et conversion
- -----------------------------------------
-
- Comme 12A.
-
-
-
- +---------------------------------------------------------------+
- | 13. GESTION DES ERREURS |
- +---------------------------------------------------------------+
-
-
- 13A. définition des gestion d'erreurs (HANDLE/EXCEPT)
- -----------------------------------------------------
-
- Le mécanisme d'exception est a peu près le même qu'en ADA ; il permet des
- réactions flexibles sur les erreurs de votre programme et les opérations
- de resources complexes.
- NOTE : le terme d'exception' en E n'a que peut de relation avec les
- exceptions venant des processeurs 680x0.
-
- Une gestion d'erreur se fait par un bout de code qui sera appelé quand une
- erreur survient lors du fonctionnement du programme, comme une fenêtre qui
- ne s'ouvre pas, ou de la mémoire non allouée. Vous, ou le système lui-même,
- dira que quelque chose ne va pas (cela s'appelle 'raising an exception' -
- 'lever une exception'), alors le système cherchera le bon gestionnaire que
- vous aurez programmé. Je dit 'le bon' car le programme peux avoir plusieurs
- gestionnaire, à chaque niveau du programme.
- Une définition de fonction normale doit (comme on le sait) ressembler à ça :
-
- PROC bla()
- /* ... */
- ENDPROC
-
- Une fonction avec un gestionnaire d'exception, à ça :
-
- PROC bla() HANDLE
- /* ... */
- EXCEPT
- /* ... */
- ENDPROC
-
- Le bloc entre PROC et EXCEPT est éxécuter normalement, et si aucune erreur
- n'arrive, le bloc ntre EXCEPT et ENDPROC est sauté. La procédure se termine
- au ENDPROC. Si une exception est levée, soit dans les partie du PROC, ou
- dans n'importe quelle fonction appelée dans ce bloc, le gestionnaire
- d'exception est invoqué.
-
- 13B. utiliser la fontion Raise()
- --------------------------------
-
- Il y a beaucoup de moyens de lever une exception, la plus simple est
- d'utiliser la fonction Raise() :
-
- Raise(exceptionID)
-
- <exceptionID> est simplement une constante qui définie le type d'exception,
- et est utilisé par les gestionnaires pour définir ce qui n'allait pas.
- Exemple :
-
- ENUM NOMEM,NOFILE /* et d'autres */
-
- PROC bla() HANDLE
- DEF mem
- IF (mem:=New(10))=NIL THEN Raise(NOMEM)
- ma_fonc()
- EXCEPT
- SELECT exception
- CASE NOMEM
- WriteF('Pas de mémoire!\n')
- /* ... et d'autres */
- ENDSELECT
- ENDPROC
-
- PROC mafonc()
- DEF mem
- IF (mem:=New(10))=NIL THEN Raise(NOMEM)
- ENDPROC
-
- La variable 'exception' dans le gestionnaire contient toujours la valeur
- de l'argument passé par la fonction Raise().
- Dans les 2 cas du New(), la fonction Raise() appel le gestionnaire de la
- fonction bla(), et retourne à la fonction qui a appelé.
- Si ma_fonc() avait son propre gestionnaire d'exception, c'est celui là qui
- serait appelé par le New() de la fonction ma_fonc(). La recherche d'un
- gestionnaire se fait dès le début de la procédure où il est définit
- jusqu'au EXCEPT, en incluant tous les appels fait à partir de là.
-
- Cela a 3 conséquences :
- A. les gestionnaires sont organisés de façon récursive. Le gestionnaire
- actuellement appelé est dépendant de la fonction appelé durant le
- fonctionnement du programme.
- B. Si une exception est levée au sein d'un gestionnaire, le gestionnaire du
- niveau inférieur (le précédent) est appelé. Cette caractèristique peut
- être utilisé pour construire des schémas d'allocation de resources
- récursives complexes avec une grande facilité, comme on l'a vu rapidement.
- C. Si une exception est levée à un niveau où aucun autre gestionnaire de
- niveau inférieur existe (ou dans un programme qui n'a pas du tout de
- gestionnaire du tout), le programme est arrêté (c'est à dire qu'un Raise(x)
- à le même effet qu'un CLeanUp(0)).
-
-
- 13C. définition des exceptions pour les fonctions prédéfinies (RAISE/IF)
- ------------------------------------------------------------------------
-
- Avec les exceptions précédentes, nous nous sommes épargné le gros travail de
- construction de notre propre fonction d'erreur. Mais il faut toujours faire
- des vérification à chaque appel de New().
-
- Le système de gestion des exceptions du E permet la définition d'exceptions
- pour toutes les fonctions du E (comme New(), OpenW, etc.) et pour toutes les
- fonction sur les bibliothèques (OpenLibrary(), AllocMem(), etc.) et même
- celles inclues dans les moidules.
-
- Syntaxe : RAISE <exceptionId> IF <fonc> <comp> <valeur> , ...
-
- La partie après RAISE peut être répétée, et séparé par une virgule ','.
- Exemple:
-
- RAISE NOMEM IF New()=NIL,
- NOLIBRARY IF OpenLibrary()=NIL
-
- La première ligne dit quelque chose comme : 'chaque fois qu'un appel de New()
- retourne NIL, alors automatiquement, lève l'exception NOMEM'.
- <comp> est l'un de ces symboles = <> > < >= <=
- Après cette défnition, vous pouvez écrire votre programme :
-
- mem:=New(taille)
-
- sans avoir à écrire :
-
- IF mem=NIL THEN Raise(NOMEM)
-
- Notez que la seule différence est que <mem> ne recoit alors aucune valeur
- si le gestionnaire est appelé : le code est généré pour tous les appels de
- New(), vérifie directement après la fin de l'éxécution de New() et appelle
- Raise() si névessaire.
-
- Nous allons implémenter un petit exemple qui serait difficile à résoudre
- sans gestion d'exceptions : on appel une fonction récursivement, et dans
- chacune on alloue une resource (dans notre cas, de la mémoire), que l'on
- alloue avant, et que l'on libère après l'appel récursif. Que se passe-t-il
- si une erreur survient quelque part loin dans la récursion ; doit-on quitter
- le programme? Oui : dans un langage conventionnel, on ne pourrait pas libérer
- les ressources plus bas dans la récursion en sortant du programme, car tous les
- pointeurs sur cette mémoire sont sauvés dans des variables locales impossibles
- à atteindre. En E, on n'a seulement qu'à lever une exception, appelant
- récursivement tous les gestionnaires et libérant toutes les ressources.
- Exemple :
-
- CONST SIZE=100000
- ENUM NOMEM /* ,... */
-
- RAISE NOMEM IF AllocMem()=NIL
-
- PROC main()
- alloc()
- ENDPROC
-
- PROC alloc() HANDLE
- DEF mem
- mem:=AllocMem(SIZE,0) /* regarde combien de bloc peuvent */
- /* être alloué */
- alloc() /* fait la récursion */
- FreeMem(mem,SIZE) /* on n'ira jamais jusqu'ici */
- EXCEPT
- IF mem THEN FreeMem(mem,SIZE)
- Raise(exception) /* appelle récursivement tous les */
- /* gestionnaires */
- ENDPROC
-
-
- C'est bien sûr une simulation d'un problême de programmation courant qui est
- beaucoup plus complexe, et la nécessité d'une gestion d'exceptions devient
- évidente. Pour un exemple concret de programme où une gestion d'erreur serait
- serait très difficile sans gestion d'exception, voir l'utilitaire 'D.e'.
-
-
- 13D. utilisation des identificateurs d'exceptions (ID)
- ------------------------------------------------------
-
- En réalité, un identificateur d'exceptions est bien sûr une valeur de 32
- bits, et vous pouvez passer pratiquement n'importe quoi à un gestionnaire
- d'exception : par exemple, certains l'utilisent pour passer des descriptions
- d'erreur.
-
- Raise('Ne peut pas ouvrir la "gadtools.library"!')
-
- En tout cas, si vous voulez bien utiliser les exceptions, et voulez avoir la
- possibilité d'utilise de futur module qui lève des exceptions non définies
- par votre programme, suivez les conseils suivants :
-
- - Utilisez et definissez l'ID 0 comme 'pas d'erreur'
-
- - Pour des exceptions particulières, utilisez des IDs de 1 à 10000.
- Définissez les avec ENUM :
-
- ENUM OK,NOMEM,NOFILE,...
-
- (OK est égale à 0, et les suivant 1+)
-
- - Les IDs de 12336 à 2054847098 sont réservés pour des exceptions courantes.
- (Ces identificateurs consistent en des lettres majuscule/minuscule de
- longueur 2, 3 ou 4, encadrés par "").
- Une exception courantes est une exception qui n'a pas besoin d'être définie
- dans votre programme, et qui peuvent être utiliser par des modules
- (incorporants aussi des fonctions) pour lever un exception :
- Par exemple, vous contruisez un ensemble de procédures qui réalisent une
- certaines tâches, et voulez lever des exceptions. Comme vous voulez utiliser
- ces fonctions dans plusieurs programmes, vous aurez du mal à coordonner les
- IDs avec le programme principal, d'autant plus dure si vous utilisez
- plusieurs ensemble de procédures, qui utilisent différents IDs pour la même
- erreur !
- C'est qu'interviennent les exceptions courantes : l'ID commun pour 'plus de
- mémoire' (out of memory) est "MEM" (avec le guillemets) : chaque
- implementation n'a qu'a appeler
-
- Raise("MEM")
-
- de n'importe quelle procedure, et le programmeur qui utilise le module
- n'a besoin que de gérer un exception qui reconnait "MEM".
-
- Les futurs modules qui contiendront des ensembles de fonctions spécifieront
- quelle exception est levée par telle procédure, et si elle prend le dessus
- sur un autre ID d' autres procédures. La tâche du programmeur qui à affaire
- aux exceptions est grandement simplifiée.
- Exemples:
-
- (système)
-
- "MEM" plus de mémoire
- "FLOW" (proche du) dépassement de la pile
- "^C" arrêt par Control-C
- "ARGS" mauvais arguments
-
- (exec/libraries)
-
- "SIG" ne peut allouer le signal
- "PORT" ne peut créer de messageport
- "LIB" bibliothèque non accessible
- "ASL" pas d' asl.library
- "UTIL" pas d' utility.library
- "LOC" pas de locale.library
- "REQ" pas de req.library
- "RT" pas de reqtools.library
- "GT" pas de gadtools.library (pareil pour les autres)
-
- (intuition/gadtools/asl)
-
- "WIN" impossible d'ouvrir une fenêtre
- "SCR" impossible d'ouvrir un écran
- "REQ" ne peut pas ouvrir une boite de requête (requester)
- "FREQ" ne peut pas ouvrir une boite de requete de fichier
- (filerequester)
- "GAD" ne peut pas créer de gadget
- "MENU" ne peut pas créer de menu(s)
-
- (dos)
-
- "OPEN" ne peut pas ouvrir le fichier / le fichier n'éxiste pas
- "OUT" problême de lecture
- "IN" problême d'écriture
- "EOF" fin de fichier (end of file) mal placé
- "FORM" mauvais format d'entrée (input format)
-
- La tendance générale est aux majuscules pour les exceptions système général
- et minuscule (et melange) pour les modules spécifiques.
-
- Tous les autres IDs (avec les IDs négatifs) sont réservés.
-
-
-
- +---------------------------------------------------------------+
- | 14. PROGRAMMATION ORIENTEE OBJET (OO) |
- +---------------------------------------------------------------+
-
-
- 14A. Les caractèristiques OO en E
- ---------------------------------
- Les caractèristiques décrite ici dans ce chapitre sont regroupés ensemble,
- car elles constituent ce qu'on définit comme les 3 composants principaux
- essentiels qui font un langage 'Orientés Objets' (ie héritage, données
- cachées, polymorphisme - inheritance, data hiding, polymorphism). Malgré tout
- en E, cela donne un chapitre séparé car chaque partie peut-être utilisée de
- plusieurs façons avec d'autres caractèristiques du E.
-
-
- 14B. héritage des objets (object inheritance)
- ---------------------------------------------
-
- C'est toujours ennuyant de ne pas pouvoir exprimer des dpendances entre des
- OBJEcTs, ou reutiliser un code qui marche sur un OBJEcTs particulier avec un
- OBEcT plus grand qui englobe le premier. L'héritage des objets vous permet
- de faire cela en E. Quand vous avez un objets a:
-
- OBJECT a
- suivant, index, terme
- ENDOBJECT
-
- vous pouvez faire un nouvel objet b qui possède les mêmes propriétés que a
- (et est compatible avec un code pour a):
-
- OBJECT b OF a
- truc, x, machin
- ENDOBJECT
-
- est équivalent à:
-
- OBJECT b
- suivant, index, terme /* venant de a */
- truc, x, machin
- ENDOBJECT
-
- Avec DEF p:b, vous ne pouvez pas directement accéder à p.truc comme d'habitude,
- mais aussi p.suivant.
-
- Comme exemple, si l'un avait un module avec un OBJEcT pour implémenter un
- certain type de donnée (par exemple une liste doublement linkée), et des PROCs
- pour les supportés, on peut simplement en hériter, ajouter des données à
- l'objet, et utilise les fonctions _éxistantes_ pour manipuler la liste.
- Toutefois, c'est à combiner avec les méthodes (décrites plus bas), l'héritage
- peut montrer sa réelle puissance.
-
-
- 14C. cacher des données (data hiding) (EXPORT/PRIVATE/PUBLIC)
- -------------------------------------------------------------
-
- Le E a un moyen très pratique pour cacher des données. D'autres langages, comme
- le C++, utilise le datahiding sur les classes, qui lève la nécessité de
- 'kludges' (comme les 'friends'), et rend le 'datahiding' peu sûr (Eiffel).
- Le 'datahiding' du E marche au niveau des module, qui peu modèliser le
- datahiding au niveau des classes, mais aussi permet des schemas plus
- intelligent.
-
- PRIVATE (privé) et PUBLIC vous permet de déclarer une section d'un objet comme
- visible pour le monde exterieure ou non; le monde exterieur est ici tout le
- code en dehors du module. Pour le code dans un module, tout est toujours
- visible.
- Exemple :
-
- OBJECT mesdonnees PRIVATE -> tout l'objet est PRIVE
- truc:PTR TO mesdonnees, chose, grrr:INT
- ENDOBJECT
-
- OBJECT aaargh
- machin:PTR TO aaargh -> public
- PRIVATE
- x:INT, y:INT, z:INT -> privé
- PUBLIC
- bof[10]:ARRAY OF mesdonnees -> de nouveau public
- ENDOBJECT
-
-
- Un objet est par défaut public, l'ajout de PRIVATE ou de PUBLIC sert
- d'interrupteur sur la visibilité des objets. Dans le premier objet, tout est
- privé. Le deuxième objet n'a que (x,y,z) de privé.
- PRIVATE et PUBLIC peuvent être mis:
- - dans la ligne d'entête des objets,
- - comme un ligne à part entière dans la définition de l'objet,
- - avant les déclarations dans une définition d'objet,
- (en fait virtuellement n'ilporte où).
-
- Pourquoi cacher des données ?
-
- Si vous voulez savoir pourquoi le 'datahiding' est une bon moyen, vous
- aurez à lire un bon livre sur l'OO (Orientation Objet). Mais en résumé:
- on remarque qu'un tas de problêmes dans la maintenance et l'amélioration
- de grandes parties de programmes viennent du fait qu'il est dur de changer
- des choses parce que du code dépend certaines structures de données dans
- votre programme. Si vous cachez un objet, seulement le code dans un module
- dépendra du format d'un objet (par exemple changer l'implémentation de la
- pile d'un tableau (ARRAY) en une liste liée (linked list)) et le code qui y
- va. Si du code d'un grande application dépend du fait que la pile est un
- tableau (ARRAY), vous ne pourrez pas simplement le changer.
- D'un manière générale, essayez de cacher des données le plus possible sans
- devenir trop restrictif sur l'utilisation de votre objet. Utiliser les
- méthodes (methods) (voir plus bas) vous permettra souvent de garder tout
- l'objet privé.
-
-
- 14D. méthodes et méthodes virtuelles
- ------------------------------------
-
- Une méthodes ressemble à un PROC, seulement maintenant il est un partie d'un
- objet. Il vous permet d'exploiterle polymorsphisme dans les objets, come nous
- le verrons plus bas.
- Définition d'un méthode:
-
- OBJECT chose PRIVATE
- x:PTR TO chose, y:INT, z
- ENDOBJECT
-
- PROC getx() OF chose IS self.x
-
-
- Le 'OF chose' dit au compilateur qu'il appartient à l'objet 'chose'.
- Notez qu'à part le 'OF', la syntaxe est identique à un PROC, cependant, il ne
- peut être appelé comme une fonction, et donc fonctionne un peu différement.
-
- 'self' est un variable locale qui est accessible dans chaque méthode, et est
- un pointeur sur l'objet auquel la méthode appartient (dans le cas présent,
- 'self:PTR TO chose'). Cette fonction retourne juste la valeur du champ x de
- chose, qui donne son sens, ce qui vous laisse la possibilité de changer ce que
- représente x.
-
- On peut appeler les méthodes de la même façon que les objets avec ".":
-
- DEF a:PTR TO blerk
- NEW a
- ...
- a.getx() -> appelle la méthode getx() sur l'objet a
-
- Dans cet exemple, à l'invocation, 'a' reçoit la valeur de 'self' pendant
- l'éxécution de getx().
-
- Autant l'utilisation des méthodes est bonne, elle ne nous a pas montrer sa
- vraie puissance, qui ne vient seulement lors de l'utlisation de l'héritage.
-
- Si j'hérite d'un objet qui a une méthode, je l'ai automatiquement dans le
- nouvel objet:
-
- OBJECT truc OF machin PRIVATE -> même que machin, + 1 champ de plus
- prut:INT
- ENDOBJECT
-
- DEF b:PTR TO truc
- NEW b
- ...
- b.getx() -> même méthode
-
- La chose interressante vient maintenant, au lieu d'hériter d'une méthode, vous
- pouvez aussi la redéfinir:
-
- PROC getx() OF chose IS self.x+1
-
- (Il va sans dire que on peut aussi de nouvelles méthodes)
- Ainsi aux places appropriées, on peut choisir de modifier légèrement le
- comportement des méthodes qu'on a d'autres objets, tant que l'interface
- (ie 'getx()') reste la même. Faire cela ne npus permet pas seulement de
- réutiliser le code selectivement, mais aussi nous permet d'utiliser le
- polymorphisme:
-
- PROC faitqquchose(o:PTR TO chose)
- ...
- o.getx()
- ...
- ENDPROC
-
- faitqquchose(a)
- faitqquchose(b)
-
- On peut appeler ce PROC aussi bien avec a que b, comme les 2 sont compatibles
- avec l'objet chose. Mais lequel des 2 implémentations de méthodes de getx()
- est appelé pour o.getx() ? Réponse: les 2. Les appels de méthodes en E sont
- ce que sont des appels de méthodes virtuelles dans d'autres langages: ils
- agissent dynamiquement sur le type réel d'un objet (o) et appelle la méthode
- appropriée.
-
- Un exemple clair:
-
- -> exemple classique de polymorphisme OO
-
- OBJECT loc
- PRIVATE xpos:INT, ypos:INT
- ENDOBJECT
-
- OBJECT point OF loc
- PRIVATE couleur:INT
- ENDOBJECT
-
- OBJECT cercle OF point
- PRIVATE rayon:INT
- ENDOBJECT
-
- PROC show() OF loc IS WriteF('Je suis en Place!\n')
- PROC show() OF point IS WriteF('Je suis un Point!\n')
- PROC show() OF cercle IS WriteF('Je suis un Cercle!\n')
-
- PROC main()
- DEF x:PTR TO loc,
- l:PTR TO loc,
- p:PTR TO point,
- c:PTR TO cercle
- ForAll({x},[NEW l,NEW p,NEW c],`x.show())
- ENDPROC
-
- Ci-dessus, x est un pointeur sur loc, beaucoup s'attendrait à x.show() pour
- écrire 'Je suis en Place' 3 fois, mais au lieu de ça, il écrit la bonne chaine
- pour chaque objet.
-
- Si quelqu'un veut écrire cet exemple dans un langage non OO, il aura besoin
- d'un SELECT pour chaque opération comme show(), de tester des valeurs
- présentes dans l'objets pour voir ce que c'est. Si je veux rajouter une nouvelle
- forme à cela, disons:
-
- OBJECT ellipse OF cercle
-
- J'aurais besoin de changer tous les SELECTs dans toute mon application. Avec
- le polymorphisme des objets, je n'écris qu'une méthode show(), et TOUT les codes
- de mon application qui appelle x.show() agirons correctement quand x est
- pointeur sur ellipse, même sans recompilation!
-
- C'est difficile de montrer pourquoi c'est si puissant en quelques exemples, et
- le meilleur moyen de le découvrir est de l'utiliser dans des applications
- réelles. Et, comme je dit, lisez un livre dessus.
-
- Comment marche le polymorphisme ?
-
- Dans les exemples ci-dessus, il est clair que le compilateur ne peut
- montrer quelle méthode il va appeler. C'est pourquoi le E utilise un
- 'objet classe' ('class object'), et chaque objet créé reçoit un
- pointeur sur cet objet. Dans l'objet classe, toutes les informations
- sont sauvées, ce qui est commun pour tous les objets de ce type, comme les
- pointeur sur les méthodes.
- Lorsque le compilateur voit un appel du style x.show(), au lieu de regarder
- directement à show() qui appartient au type de 'x' (ie loc), il générera un
- code pour retrouver le pointeur sur la méthode show() à partir de l'objet
- classe 'loc'. Si tant que l'objet classe pour 'point' regarde la même chose
- que 'loc' (seulement peut-être un peu plus grand), ce code appellera
- automatiquement le show() de 'point', si 'x' est réellement un objet
- 'point'. On appelle ça souvent 'runtime binding'.
-
- Des objets qui ont des méthodes, sont par conséquent 4 octets plus grand que
- vous pensez qu'ils sont, si ils contiennent un pointeur objet classe. Ce
- pointeur est automatiquement installé par NEW, c'est la raison pour laquelle
- NEW _pour le moment_ est la seule façon de crée un tel objet.
-
- Si une méthode est déclarée avec le seul but qui permette à des classes
- secondaires ('subclasses') de la redéfinir (ce type de classe est connu comme
- une classe de base virtuelle ('virtual baseclass') dans certains langages),
- vous pouvez utiliser EMPTY:
-
- PROC truc() OF bidule IS EMPTY
-
- On peut effectivement ajouter des méthodes aux objets système:
-
- OBJECT mongadget OF gadget -> à partir d'intuition!
- -> champ supplémentaire ici
- ENDOBJECT
-
- PROC creergadget() OF mongadget IS ...
-
-
-
- +---------------------------------------------------------------+
- | 15. ASSEMBLEUR EN LIGNE |
- +---------------------------------------------------------------+
-
-
- 15A. utilisation des identificateurs
- ------------------------------------
-
- Comme vous l'aurez préssenti dans l'exemple du chapitre 5D, les instructions
- assembleurs peuvent librement mélangé avec le code E. Le grand secret est
- qu'un assembleur complet est construit dans le compilateur.
- En plus des modes d'adressage assembleur normaux, vous pouvez utiliser les
- identificateurs suivant :
-
- mylabel:
- LEA mylabel(PC),A1 /* labels */
-
- DEF a /* variables */
- MOVE.L (A0)+,a /* notez que <var> est un <offset>(A4) */
- /* (or A5) */
-
- MOVE.L dosbase,A6 /* identificateur d'appel */
- /* d'un bibliothèque */
- JSR Output(A6)
-
- MOVEQ #TRUE,D0 /* constantes */
-
-
- 15B. l'assembleur en ligne comparé à un macro assembleur
- --------------------------------------------------------
-
- L'assembleur en ligne diffère un peu d'un macro assembleur moyen, et ce à
- cause du fait que c'est une extension du E, et qu'il obéit à la syntaxe du E.
- Les grosses différences sont :
-
- - les commentaires sont fait avec /* et */ et non par ';', ils ont une
- significations différentes.
- - les mots-clé et registres sont en majuscules, tout est sensible (case
- sensitive).
- - pas de macros ou autres (Il y a le langage E fait pour ça !)
- - vous devez faire attention que les registres A4/A5 ne sont pas détruit par
- un code assembleur en ligne, car utilisé par le E.
- - pas _encore_ de support pour le modèle LARGE/reloc-hunks en assembleur.
- Cela siginifie en pratique que vous devz utiliser un adressage relativ pour
- l'instant.
-
-
- 15C. comment utiliser des données binaires (INCBIN/CHAR..)
- ----------------------------------------------------------
-
- INCBIN
-
- syntaxe: INCBIN <nom_fichier>
-
- inclue un fichier binaire a ce point précis, doit être séparé du code.
- Exemple:
-
- montab: INCBIN 'df1:data/blabla.bin'
-
-
- LONG, INT, CHAR
-
- syntaxe: LONG <valeurs>,...
- INT <valeurs>,...
- CHAR <valeurs>,...
-
- vous permet de placer des données binaires dans votre programme comme
- DC.x en assembleur. Notez que la déclaration CHAR prend aussi les chaines,
- et sera toujours mis à un mot pair.
- Exemple :
-
- mes_données: LONG 1,2; CHAR 3,4,'Salut !',0,1
-
-
- 15D. OPT ASM
- ------------
-
- On peut trouver quelques autres détails sur OPT ASM dans le chapitre 16A.
- Cette option vous permet de mettre 'EC' en mode assembleur. Il n'y a aucune
- bonne raison d'utiliser EC plutôt que quelques macro-assembleurs à part le
- fait qu'il est significativement plus rapide que par exemple A68k, égale
- DevPac et est derrière ASmOne (snif... 8-{). Vous passerez aussi beaucoup de
- temps en essayant de réduire le nombre de disquettes des bons vieux sources
- du Seka via EC, à cause des différences décrites dans la chapitre 15B. Si vous
- voulez écrire un programme en assembleur avec EC, et voulez rendre le source
- compatible avec d'autres assembleurs, simplement faites précéder chaque
- élément spécifique du E d'un ';', EC les utilisera mais les autres assembleurs
- les verrons comme commentaires.
- Exemple :
-
- ; OPT ASM
-
- start: MOVEQ #1,D0 ; /* faite n'importe quoi */
- RTS ; /* et sort */
-
- Ceci sera assemblé par n'importe quel assembleur, même EC
-
-
- 15E. Assembleur en ligne et registres de variables
- --------------------------------------------------
-
- Les variables de registres sont de bons compagnions de l'assembleur en ligne,
- car ils fonctionnent justement comme des registres, mais en même temps possède
- des identificateurs clairs au lieu de Dx, et aussi sont automatiquement sauvés
- et restauré par le code E.
- Exemple:
-
- PROC bla()
- DEF compte:REG
- MOVEQ #10,compte
- boucle: WriteF('compte=\d\n',compte)
- DBRA compte,boucle
- ENDPROC
-
- Toutes les instructions qui peuvent travailler avec Dx EA, marche avec les
- variables de registre.
- Exemples:
-
- MOVEQ #1,a
- MOVEM.L D0/D1/a/b/A0,-(A7)
- LSL.L a,b
-
- etc.
-
- Comme vous le savez, EC utilise D3-D7 pour ses variables de registres. Si vous
- voulez écrire un code qui mélange de l'assembleur avec le E, il est préférable
- de garder des valeurs à long terme des les variables de registres, et les
- temporaires dans d0-D2/A0-A3/A6.
-
-
-
- +---------------------------------------------------------------+
- | 16. REVUE D'IMPLEMENTATION ET TECHNIQUE |
- +---------------------------------------------------------------+
-
-
- 16A. le mot-clé OPT
- -------------------
-
- OPT, LARGE, STACK, ASM, NOWARN, DIR, OSVERSION, MODULE, EXPORT, RTD, REG
-
- syntaxe: OPT <options>,...
- vous permet de changer les options par défaut du compilateur :
-
- LARGE met le modèle de données et du code sur grand (LARGE).
- Petit par défaut. Le compilateur génère un code 100%
- relatif de style pc, avec un taile maximum de 32k. Avec
- LARGE, il n'y a pas de limites, et reloc-hunks est généré.
- Voir 0D, LARGE
- STACK=x fixe la taille de la pile à x octets. A utiliser
- uniquement si vous savez ce que vous faites. Normalement
- le compilateur fait une bonne approximation de l'espace
- nécessaire.
- ASM met le compilateur en mode assembleur. A partir de là,
- uniquement des instructions assembleur sont acceptés, et
- aucun code d'initialisation n'est généré. Voir le chapitre
- assembleur en ligne 16C.
- NOWARN Ne fait pas afficher les avertissements. Le compilateur
- vous préviendra si il *pense* que votre programme est
- incorrect, mais a une bonne syntaxe. Voir 0D, NOWARN
- DIR=moduledir fixe le répertoire dans lequel le compilateur cherchera
- les modules. 'Emodules:' par défault
- OSVERSION=ver =33 par défaut (v1.2). Fixe la version minimum du
- kickstart (comme 37 pour v2.04)sur lequel votre programme
- doit tourner. Comme ca, votre programme ne s'arrêtera lors
- de l'ouverture de la dos.library si vous avez une ancienne
- machine. En tout cas, vérifiez vous-même la version et
- donner un message d'erreur approprié sera une aide à
- l'utilisateur.
- MODULE fait considérer le source comme module. (voir 10C)
- EXPORT exporte automatiquement toutes les déclarations dans le
- source principal.
- RTD génère RTD au lieu de RTS dans le source principal.
- 020+ seulement. [optimisation expérimentale]
- 020,881,040 génère un code pour utilisation avec ces puces. Pas
- vraiment utilisable encore.
-
- Exemple:
-
- OPT STACK=20000,NOWARN,DIR='df1:modules',OSVERSION=39,REG=3
-
-
- 16B. petit et grand modèle
- --------------------------
-
- L'Amiga E vous laisse le choix entre un petit (SMALL) et un grand (LARGE)
- modèle. Notez que la plupart des programmes que vous écrirez (spécialement si
- vous débutez en E) rentrera dans les 32 Ko une fois compilés : vous n'aurez
- pas à vous soucier du modèle du code. Vous saurez qu'il faudra utiliser le
- grand modèle dès que EC commencera à dire qu'il ne peut plus réduire le code
- à 32k. Pour compiler un source avec un grand modèle :
-
- 1> ec -l grand.e
-
- ou mieux encore, mettez
-
- OPT LARGE
-
- dans votre code.
-
-
- 16C. organisation de la pile
- ----------------------------
-
- Pour garder les variables locales et globales, le système d'un éxécutable
- généré par Amiga E alloue un bloc de mémoire, duquel il prendra un bout pour
- les variables globales. Le reste sera utilisé dynamiquement par les appels
- des fonctions.
-
- Quand une fonction est appelé en E, un espace dans la pile est reservée
- pour les données locales, qui sera libéré à la sortie de la fonction.
- C'est pourquoi avoir un grand tableau comme données locales peut être
- dangereux si utilisé récursivement : toutes les données de lappel précédent
- de la même fonction reste dans la pile, et consomme une grande partie de la
- pile encore libre. Toutefois si les procédures sont correctement appelées,
- il n'y a aucune raison d'avoir un débordement.
- Exemple:
-
- donnée globale : 10k (par ex. un tableau)
- donnée locale PROC #1: 1k
- donnée locale PORC #1: 3k
-
- Le système reserve toujours 10k d'espace supplémentaire pour les récursions
- normales (par exemple avec un petit tableau local) et des espaces pour des
- tampons (buffers) et le système, qui prendront en tout 24 k de pile en plus.
-
-
- 16D. limites du code
- --------------------
-
- Notez ces signes : (+-) = dépend du contexte
- (n.l.) = pas de limite, mais semble raisonnable.
-
- --------------------------------------------------------------------------
- OBJECT/ITEM (objet/membre) SIZE/AMOUNT/MAX (taille)
- --------------------------------------------------------------------------
-
- type de donnée CHAR 0 .. 255
- type de donnée INT -32 k .. +32 k
- type de donnée LONG/PTR -2 gig .. +2 giga
-
- longueur d'identificateur 100 octets (n.l.)
- longueur d'un ligne de commandes 2000 tokens léxicaux(+-)
- longueur d'un source 2 giga (théoriquement)
- listes de constantes quelques 100aines (+-)
- chaines constantes 1000 chars (n.l.)
- nombre max. de boucle imbriqué (IF, FOR etc.) 500
- nombre max. de commentaire imbriqué infini
-
- # de variables locales par procédure 8000
- # de variables globales 7500
- # d'arguments pour vos propres fonctions 8000 (ensemble avec locales)
- # d'arguments de fonction E (WriteF()) 64
-
- un objet (alloué en local/global ou dyn.) 8 k
- un tableau, liste ou chaine (local or global) 32 k
- une chaine (dynamique) 32 k
- une liste (dynamique) 128 k
- un tableau (dynamique) 2 giga
- des objets avec NEW 64 k élem.
- CHAR/INT/LONG/ avec NEW 2 giga
-
- données locales par procédure 250 méga
- données globales 250 méga
-
- taille du code d'une procédure 32 k
- taille du code d'un éxécutable 32 k en petit (SMALL) modèle,
- 2 giga en grand (LARGE) modèle
- limite courante (étendu dans la futur) 2-5 méga
-
- taille des tampons du code généré
- et des identificateurs suivant le source
- taille des tampons des labels/branches et
- intermédiaire (re) alloué indépendamment
-
-
- 16E. les messages d'erreurs, d'avertissements et de non référence
- -----------------------------------------------------------------
-
- Quelques fois, à la compilation de votre source avec EC, vous aurez un
- message du style : UNREFFRENCED: <ident>, <ident>, ...
- C'est le cas si vous déclarez des variables, fonctions ou labels dont vous
- ne vous servez pas. C'est en service qui vous est rendu par le compilateur
- pour vous aidez à trouver ces erreurs difficiles à trouver.
-
- Il y a plusieurs avertissements que le compilateur envoie pour vous dire que
- quelquechose devrait mal se passer, mais n'est pas vraiment une erreur.
-
-
- - 'A4/A5 used in inline assembly' 'A4/A5 utilisé dans les lignes assembleur'
-
- Cet avertissment apparait lorsque vous utilisez les registres A4 ou A5 dans
- votre code. La raison de cela est que ces registres sont utilisé de façon
- interne par le E pour adreser les variables globales et locales.
- Bien sûr il y a de bonne raison de les utiliser, comme pour faire un
- MOVEM.L A4/A5,-(A7) avant un grand morceau de code assembleur.
-
-
- - 'keep an eye on your stacksize' 'jetez un oeil à la taile de votre pile'
- - 'stack is definitely too small' 'la pile est vraiment trop petite'
-
- Ces deux apparaitrons si vcous utilisez OPT STACK=<size>. Le compilateur
- comparera votre taille à sa propre estimation (voir le chapitre 16C), et
- retournera la première des erreurs si il pense que c'est bien mais un peu
- juste, et la seconde si c'est bien trop petit.
-
-
- - 'suspicious use of "=" in void expressions (s). (line %d)'
- 'mauvaise utilisation de "=" dans une expression vide (s). (ligne %d)'
-
- Cet avertissment sera retourné si vous écrivez des expressions comme 'a=1'
- comme déclaration. Un raison de cela est le fait qu'un comparaison n'a pas
- de sens comme déclaration, mais la principale raison est que cela provient
- souvent d'une faute de frappe en voulant écrire 'a:=1'. Oublier ces ':'
- serait difficile à trouver, et aurait des conséquences désastreuses.
-
-
- - 'module changed OPT settings' 'changement des OPTs par le module'
-
- Si vous utilisez un module qui a OPT OSVERSION=37, cette modification
- affecte aussi l'OPT du programme principal. Cette alerte sert à vous en
- rappeler. Mettez un OPT identique dans le programme principal pour
- l'enlever.
-
-
- - 'variable used as function' 'variable utilisée comme fonction'
-
- Dans la v3, des variables arbitraires peuvent être utilisées comme fonction.
- Cette fonction est là pouyr vous prévenir de ne pas le faire
- accidentellement.
-
-
- - 'code outside PROCs'
-
- Vous avez écrit du code E entre 2 PROC, ce qui est rarement utile.
-
-
- Erreurs.
- Le compilateur affichera la ligne du code source qui a causé l'erreur ; et
- un curseur en indiquera l'endroit précis. Le curseur indique le point où le
- compilateur était quan il a _découvert_ l'erreur, il est donc certain que le
- symbole qui a provoqué l'erreur est celui juste _avant_ le curseur.
-
- - 'syntax error' 'Erreur de syntaxe'
-
- Erreur le plus souvent rencontrée. Cette erreur survient soit
- lorsqu'aucune autre erreur est appriopriée, soit l'agencment de votre
- code est anormal.
-
-
- - 'unknown keyword/const' 'mot-clé ou constantes inconnus'
-
- Vous avez utilisé un identificateur en majuscule (comme 'IF' ou 'TRUE'),
- et le compilateur ne trouve aucune définition. Causes :
- - mot-clé mal écrit,
- - vous utilisez une constante, mais vous avez oublié de la définir dans
- la déclaration d'un CONST,
- - vous avez oublié to spécifier le module dans lequel la constante est
- définie.
-
-
- - '":=" expected' '":=" nécessaire'
-
- Vous avez écrit un FOR ou un assignement, et écrit quelque chose d'autre
- que ':='.
-
-
- - 'unexpected characters in line' 'caractères non corrects dans la ligne'
-
- Vous utilisez des caratères en dehors d'une chaine, et qui n'ont aucun
- sens pour le E
- Exemple : @, !, &, \, ~
-
-
- - 'label expected' 'label nécessaire'
-
- A certains endroits, par exemple aprés un PROC ou un JUMP, un label est
- nécessaire, et vous avez écrit autre chose.
-
-
- - '"," expected' '"," nécessaire'
-
- En spécifiant une list d'éléments (par exemple une liste de paramètres)
- vous avez écrit quelque chose d'autre à la place de la virgule.
-
-
- - 'variable expected' 'variable nécessaire'
-
- Cette construction demande un variable.
- Exemple :
- FOR <var>:= ... etc.
-
-
- - 'value does not fit in 32 bit' 'valeur ne rentre pas dans les 32 bits'
-
- En spécifiant une constante (voir les chapitres 2A-2E), vous avez écrit
- un nombre trop grand (par exemple : $FFFFFFFFF, "abcdef").
- Cette erreur apparait aussi lorsque vous définissez plus de 32 éléments
- dans la déclaration d'un SET.
-
-
- - 'missing apostrophe/quote' 'apostrophe/cote manquante'
-
- Vous avez oublié une ' à la fin de la chaine.
-
-
- - 'incoherent program structure' 'structure incohérente du programme'
-
- - vous avez commencé une nouvelle procédure (PROC) avant de terminer
- la précédente.
- - vous n'avez pas correctement inclue les boucles les unes dans les
- autres.
- Exemple :
- FOR
- IF
- ENDFOR /* inversion du ENDFOR et du ENDIF */
- ENDIF
-
-
- - 'illegal command-line option' 'mauvaise option dans la ligne de commande'
-
- En spécifiant 'EC -opt source' vous avez écrit les options avec quelque
- chose que EC ne connait pas.
-
-
- - 'division and multiplication 16bit only'
- 'division et multiplication seulement sur 16 bits'
-
- Le compilateur a détecté que vous utilisez des valeurs sur 32 bits pour
- * ou /. Cela ne donnera pas la valeur désiré lorsque le programme sera
- lancé. Voir Mul() et Div().
-
-
- - 'superfluous items in expression/statement'
- 'trop de membres dans l'expression/déclaration'
-
- Après la compilation, le compilateur trouve touours des 'tokens' au lieu
- d'une fin de fichier (end of line). Vous avez probablement oublié une
- saut de ligne <lf> ou un ';' pour séparer 2 déclarations.
-
-
- - 'procedure "main" not available' 'pas de procédure Main()'
-
- Votre programme n'a pas de proceédure Main() !
-
-
- - 'double declaration of label' 'double déclaration d'un label'
-
- Vous avez déclaré 2 fois un label.
- Exemple :
- label:
- PROC label()
-
-
- - 'unsafe use of "*" or "/"' 'utilisation peu prudente de "*" ou "/"'
-
- Ceci encore concerne les 16 bits au lieu des opérateur 32 bits * ey /.
- Voir 'division and multiplication 16bit only'.
-
-
- - "reading sourcefile didn't succeed"
- 'la lecture du fichier source n'a pas réussi'
-
- Vérifiez votre source, en particulier si en donnant 'ec monsource',
- assurez vous que le nom du fichier se termine par '.e' (ce qui n'est pas
- le cas dans la ligne de commande)
-
-
- - "writing executable didn't succeed"
- 'l'écriture de l'éxécutable n'a pas réussi'
-
- En écrivant le code généré, comme éxécutable, le DOS retourne une erreur.
- Par exemple, l'éxécutable déja existant ne peut être effacé et réécrit.
-
-
- - 'no args' 'pas d'arguments'
- "USAGE: ec [-opts] <sourcecodefilename> (`.e' is added)"
- "USAGE: ec [-opts] <nom_du_fichier_soure> (`.e' est rajouté)"
-
- Vous aurez ceci en tapant uniquement 'ec', sans arguments.
-
-
- - 'unknown/illegal addressing mode' 'mode d'adressage inconnu/illégal'
-
- Cette erreur est retourné uniquement par les lignes assembleur. Les causes
- possibles sont :
- - vous avez utilisé un mode d'adressage qui n'éxiste pas sur le 68000,
- - le mode d'adressage éxiste, mais pas pour cette instruction.
- Toutes les instructions assembleur ne supporte pas tutes les
- combinaisons d'adresses effective comme source et destination.
-
-
- - 'unmatched parentheses' 'mauvais nombre de parenthèses'
-
- Votre déclaration comporte plus de '(' que de ')' ou l'inverse.
-
-
- - 'double declaration' 'double déclaration'
-
- Un identificateur est utilisé dans 2 ou plus déclarations.
-
-
- - 'unknown identifier' 'identificateur inconnu'
-
- Un identificateur n'est utilisé dans aucune déclaration; il est inconnu.
- Vous avez certainement oublié de le mettre dans la déclaration DEF.
-
-
- - 'incorrect #of args or use of ()' 'nombre incorrect d'arguments ou de ()'
-
- - vous avez oublié de mettre une '(' ou une ')' au bon endroit,
- - vous donner un nombre incorrect d'argument à un fonction.
-
-
- - 'unknown e/library function' 'fonction inconnue du E/bibliothèque'
-
- Vous avez écrit un identificateur avec le premier caractère en majuscule,
- et le second en minuscule, mais le compilateur ne trouve aucune
- définition. Causes possibles :
- - le nom de la fonction est mal écrit,
- - vous avez oublié d'inclure le module qui défini l'appel de la
- bibliothèque.
-
-
- - 'illegal function call' 'appel de fonction illégal'
-
- N'arrive que rarement. Vous l'aurez si vous essayez de construire
- des appels de fonction complexe, comme :
- WriteF(WriteF('hi!'))
-
-
- - 'unknown format code following "\"' 'format du code suivant "\" inconnu'
-
- Vous spécifiez un code de format dans une chaine, qui est illégal.
- Voir le chapitre 2F pour une liste des codes de format.
-
-
- - '/* not properly nested comment structure */'
- '/* commentaires mal imbriqués */'
-
- Le nombre de '/*' n'est pas égal au nombre de '*/', ou placé dans un
- ordre bizarre.
-
-
- - 'could not load binary' 'ne peut pas ouvrir la bibliothèque'
-
- le fichier spécifié dans le ligne INCBIN <fichier> ne peut pas être lu.
-
-
- - '"}" expected' '"}" nécessaire'
-
- Vous avez commencé une expression comme '{<var>', et vous avez oublié
- le "}".
-
-
- - 'immediate value expected' 'valeur immédiate nécessaire'
-
- Certaines constructions demandent une valeur immédiate à la place d'une
- expression.
- Exemple :
- DEF s[x*y]:STRING /* mauvais :uniquement quelque chose comme */
- /* s[100]:STRING est bon */
-
-
- - 'incorrect size of value' 'taille de la valeur incorrecte'
-
- Vous spécifiez une valeur trop grande (ou trop petite).
- Exemples:
- DEF s[-1]:STRING, t[1000000]:STRING /* doit être entre 0..32000 */
- MOVEQ #1000,D2 /* doit être entre -128..127 */
-
-
- - 'no e code allowed in assembly modus'
- 'pas de code E accepté en mode assembleur'
-
- Vous voulez compiler en mode assembleur, en écrivant 'OPT ASM', et par
- accident, vous avez mis du code E.
-
-
- - 'illegal/inappropriate type' 'type inapproprié/illégal'
-
- A certain endroit ou un <type> est demandé, vous avez écrit quelque chose
- d'inaproprié.
- Exemple :
- DEF a:PTR TO ARRAY /* aucun type de ce type :) */
- [1,2,3]:STRING
-
-
- - '"]" expected' '"]" nécessaire'
-
- Vous avez commencé avec un "[", mais vous avez oublié de terminer
- avec un "]".
-
-
- - 'statement out of local/global scope'
- 'déclaration en dehors des déclarations locales ou globales'
-
- Un point de déclaration est la première déclaration PROC. Avant ça,
- uniquement des définitions globales (DEF, CONST, MODULE, etc) sont
- permises, et aucun code. Dans la secondes parties, seulement les
- définitions de code et de fonctions sont légales, aucune définition
- globale n'est possible.
-
-
- - 'could not read module correctly' 'ne peut lire le module correctement'
-
- Une erreur du DOS est survenue en voulant lire un module à partir de la
- déclaration MODULE. Causes :
- - 'Emodules:' est mal assigné,
- - le nom du module est mal écrit, ou n'éxiste pas,
- - vous avez écrit MODULE 'bla.m' au lieu de 'bla' (sans suffixe).
-
-
- - 'workspace full!' 'espace de travial plein !'
-
- N'arrive que rarement. Si cela survient, you devez mettre l'option '-m'
- pour forcer manuellement EC à faire une estimation plus large sur la
- quantité de mémoire nécessaire.
- Essayez de compiler avec -m2, puis -m3 jusqu'à ce que l'erreur
- disparaisse. Vous aurez certainement écrit une gigantesque application
- avec une grande quantité de données pour arriver à cette erreur.
-
-
- - 'not enough memory while (re-)allocating'
- 'pas assez de mémoire pendant la (ré)allocation'
-
- Tout simplement. Solutions possibles :
- 1. vous avez plusieurs programmes marchant en multitache. Quittez en
- quelques uns et reéssayez.
- 2. il vous reste peu de mémoire, ou votre mémoire est fragmentée.
- 3. aucun des 2 possibilités. Achetez de la mémoire (Hum..)
-
-
- - 'incorrect object definition' 'définition d'objet incorrect'
-
- Vous avez écrit quelque chose en OBJECT et ENDOBJECT qui n'est pas
- correct. Voir le chapitre 8F pour savoir comment bien écrire.
-
-
- - 'illegal use of/reference to object'
- 'mauvaise utilisation ou référence à un objet'
-
- Si vous utilisez une expressions comme ptr.membre, membre doit être un
- membre définit dans l'object ptr.
-
-
- - 'incomplete if-then-else expression' 'expression if-then-else incomplète'
-
- Si vous utilisez IF comme opérateur (chapitre 4E), alors un ELSE doit
- être présent : une expression avec un IF à l'interieur a toujours besoin
- de retourner une valeur, alors qu'une déclaration avec un IF peut ne rien
- faire si aucun ELSE n'est présent.
-
-
- - 'unknown object identifier' 'identificateur d'objet inconnu'
-
- Vous utilisez un identificateur qui est reconnu par le compilateur comme
- une partie d'un objet, et vous avez oublié de le déclarer. Causes :
- - nom mal écrit,
- - module manquant,
- - l'identificateur dans le module est écrit différemment de ce que vous
- pensiez (des RKRM par exemple) Vérifiez avec ShowModule.
- Notez que le système d'objet Amiga hérite des identificateurs de
- l'assembleur, pas du C. Les identificateurs obéissent à la syntaxe
- du E.
-
-
- - 'double declaration of object identifier'
- 'double déclaration d'idenficateur d'objet'
-
- Un identificateur est utilisé dans le définition de 2 objets.
-
-
- - 'reference(s) out of 32k range: switch to LARGE model'
- 'référence(s) en dehors des 32ko : utilisez le grand modèle'
-
- Votre programme est plus grand que 32ko. Mettez simplement 'OPT LARGE'
- dans votre code source. Voir le chapitre 16B.
-
-
- - 'reference(s) out of 256 byte range' 'référence(s) en dehors des 256 octets'
-
- Vous avez probablement écrit BRA.S ou Bcc.S sur un trop grand espace.
-
-
- - 'too sizy expression' 'expression trop grande'
-
- Vous utilisez une liste, qui est peut-être récursivment, qui est trop
- grande.
-
-
- - 'incomplete exception handler definition'
- 'définition incomplète du gestionnaire d'exception'
-
- Vous avez certainement utilisé EXCEPT sans HANDLE, ou quelque chose dans
- ce genre. Voir le chapitre 13A sur les gestions d'exception.
-
- - 'not allowed in a module' 'non permis dans un module'
-
- Vous faites quelques choses que vous ne pouvez pas faire dans un module,
- comme des variables globales avec initialisations.
-
- - 'allowed in modules only' 'permis uniquement dansles modules'
-
- Vous avez certainmenet utiliser EXPORT dans le programme principal.
-
- - 'this doesn't make sense' 'ça n'a aucun sens'
-
- Erreur générale.
-
- - 'you need a newer version of EC for this :-)'
- 'vous avez besoin d'une version récente de EC pour ça :-)'
-
- Vous utilisez certainement un module qui a été compiler avec un version
- plus récente de EC, que la votre.
-
- - 'no matching "["' 'pas de "["'
-
- Dans une déclaration, un "]" a été trouvé, mais pas son "]" correspondant.
-
- - 'this instruction needs a better CPU/FPU (see OPT)'
- 'cette instruction a besoin d'un CPU/FPU plus puissant (voir OPT)'
-
- Vous utilisez une construction (probablement une instruction asm) qui
- nécessite un OPT 020 ou ce genre.
-
- - 'object doesn't understand this method'
- 'l'objet ne comprend pas cette méthode'
-
- Vous invoquez une méthode sur un objet qui n'est pas défini pour ce type.
-
- - 'method doesn't have same #of args as method of baseclass'
- 'la méthode n'a pas le même nombre d'argument que la méthode de base'
-
- Si vous redefinissez une méthode, vous devez vous assurer que la nouvelle
- a le même nombre d'argument que l'original.
-
- - 'toomuch register variables in this function'
- 'trop de variables de registre dans cette fonction'
-
- Si vous utilisez :REG pour assigner des variables de registre vous mêmes,
- vous ne pouyvez actuellement pas en utiliser plus de 5.
-
- - 'Linker can't find all symbols'
- 'le linker ne peut trouver tous les symboles'
-
- Si vous utilisez un module A qui utilise un module B, B doit être linké.
- A se trouve dans certain PROCs de B, et si B est recompilé sans ces PROCs,
- le linker aura des problêmes à rassembler le tout dans l'éxécutable.
-
- - 'could not open "mathieeesingbas.library"'
- 'ne peut ouvrir la 'mathieeesingbas.library"'
- Si vous utilisez un code flottant, le compilateur lui même aura besoin
- de fonctions flottantes pour être capable de générer le code.
-
- - 'illegal destructor definition' 'définition illégale de destruction'
-
- Vous avez défini une méthode end() avec des arguments ou une valeur de
- retour.
-
- - 'implicit initialisation of private members'
- 'initialisation implicite de membres privés'
-
- Vous avez écrit une expression [...] ou NEW [...] qui des parties privées.
-
- - 'double method declaration' 'déclaration de méthode double'
-
- Vous avez défini une méthode pour cet objet 2 fois.
-
-
- 16F. organisation et allocation des tampons (buffer) du compilateur
- -------------------------------------------------------------------
-
- Quand vous recevez une erreur 'workspace full' (espace de travail plein)
- (peu probable), ou si vous voulez savoir ce qui se passe quand votre
- programme est compilé, il est utile de savoir comment EC organise ses
- tampons.
-
- Un compilateur, et c'est le cas d'EC, a besoin de tampons (buffers) pour le
- suivi de beaucoup de choses, comme les identificateurs, etc., et pour y
- mettre le code généré. EC ne sait pas de quelle taille doivent être les
- tampons. Pour certains, ceux par exemple pour garder les constantes, il n'y
- a pas de problêmes : si le tampons est plein lors de la compilation, EC alloue
- un nouveau tampon et continue. D'autres tampons, comme celui réservé au code
- généré, doit être continue en mémoire et ne peut être déplacé pendant la
- compilation : EC doit donc faire une bonne estimation de la taille des tampons
- pour être capable de compiler des sources de toutes tailles.
- Pour faire cela, EC calcule la mémoire nécessaire suivant le cas du source
- donné. Dans 99% des cas, EC aura alloué suffisament de mémoire pour compiler
- quasiment tous les sources. Dans les autres cas, vous aurez un erreur à la
- compilation et vous aurez à spécifier plus de mémoire grace à l'option '-m'.
-
- Essayez les différents sources (de taille et de type différent) en les
- combinant avec l'option '-b', pour voir comment ca marche en réalité.
-
-
- 16G. allocation de registres
- ----------------------------
-
- E v3 supporte une allocation de registre, qui est une techinque pour garder
- des variables dans des registres au lieu de la pile. Pour un code normal
- qui utilise des routines OS, vous ne moterez pas trop la différence, mais pour
- des petites boucles, cette optimisation peut faireun grande différence. Il y
- a 2 moyens d'utiliser l'allocation:
-
- - avec l'option REG.
- Si vous écrivez par exemple EC REG=3 truc.e, (max=5, pour le moment) EC
- calculera pour chaque PROC les variables les plus utilisées dans les
- registres. L'allocation des registres est une technique qui essaye d'être
- intelligente: elle calculera pour chaque variable un poids, par exemple une
- variable utilisée dans une boucle FOR aura un poids plus fort qu'une
- variable en dehors, et une dans un IF aura un poids plus faible. Ces poids
- sont combinés, donc un WHILE dans un FOR donnera un poids plutôt élevé.
-
- - DIY: vous pouvez mettre le mot-clef REG devant n'importe quel type dans une
- déclaration, par exemple:
-
- DEF x:REG, s[4]:REG LIST
-
- vous pouvez faire cela si vous n'avez pas confiance à l'allocataire de
- registres, ou si vous voulez affiner juste un PROC. Vous pouvez même utiliser
- les deux ensembles: si dans un PROC vous avez une variable avec :REG,
- compiler avec REG=5 permettra à EC de faire les 4 restant de lui-même.
-
- Le défaut est REG=0, donc EC marche plutôt comme les anciennes versions.
-
- Les variables qui PEUVENT être allouées sont uniquement des variables locales
- qui ne sont pas des paramêtres. Aussi, si vous prenez l'adresse d'une variable
- avec {} elle ne peut être mise dansun registre (devinez pourquoi...). Les
- registres ne peuvent pas être alloués dans des PROCs qui ont une gestion
- d'exception, pour le moment.
-
- Il y a quelques petites choses à noter lors de l'utilisation de registres:
- - cette partie de EC est en ce moment 3.0a a été testé pour être fiable,
- mais vérifiez toujours que ce comportement est le même qu'un code
- non alloué. Ca _doit_ marcher, mais il est trop tôt pour le garantir :-)
- En résumé: soyez prudent pour le moment quand vous appliquez ces
- techniques ;
- - EC utilise les registres D7..D3 pour les variables, ainsi si vous
- utilisez de l'assembleur, vous devez vérifiez que les PROCS qui utilise
- l'allocation de registre ou :REG ne se plante pas (voir 15E).
- Le code généré pour un PROC sauve automatiquement les registres qu'il
- utilise pour protéger le code qui l'appelle ;
- - conseil : compiler avec REG=5 n'est pas le plus rapide, tant que la
- sauvegarde de variables sur des appels de fonction/bibliothèque aussi
- s'attire un 'overhead'. REG=3 peut être mieux pour certains cas. Aussi si
- _tous_ les codes en question se rapportea des appels de bibliothèques au
- lieu de calcul pur, ne vous attendez pas à un gain dans les registres.
-
- -> l'allocation de registres rendrait ce programme 2 fois plus rapide.
-
- PROC main()
- DEF a,b=10,c=20,d
- FOR a:=1 TO 1000000 DO d:=b+c
- ENDPROC
-
- -> en gros 5% plus rapide quand on utilise l'allocation de registres
-
- PROC main()
- DEF a,s[100]:STRING,t
- t:='putting "a" in a reg won''t give that much of a speedup, I think.'
- FOR a:=1 TO 100000 DO StrCopy(s,t)
- ENDPROC
-
-
-
- +---------------------------------------------------------------+
- | 17. Les Utilitaires Essentiels du E |
- +---------------------------------------------------------------+
-
-
- 17A. bin/showmodule
- -------------------
-
- Comme vous l'aurez remarqué, l'équivalent des includes du E, les modules,
- sont des fichiers binaires, comme ceux du compilateur Modula2, par exemple.
- Pour afficher leur contenu de ces fichiers, en bon texte ASCII, vous devez
- utiliser 'showmodule' :
-
- showmodule <modulespec>
-
- Exemples:
-
- 1> showmodule emodules:intuition/intuition
- 1> showmodule >gadtools.txt emodules:gadtools
-
- Notez que showmodule écrit par défaut sur la console, et peut être arrêté
- par CTRL-C.
-
-
-
- 17B. sources/utilitaires/showhunk.e, bin/showhunk
- -----------------------------------------------
-
- Affiche tous les types de fichiers éxécutables, ainsi que les fichiers
- objets '.o' généré par d'autre compilateurs/assembleurs.
- ShowHunk vous affichera dans une (très simple) forme, la structure des
- éxécutables générés par EC, mais aussi supporte des fichiers overlay
- complexes. Dumpe aussi les labels (comme les XREF et les XDEF).
-
- Le plus important, ShowHunk possède un désassembleur pour les code-hunks.
- Mettez l'option 'DISASM/S'
-
- Exemple :
-
- showhunk <exefile>
-
- Comme: 1> showhunk helloworld
- 1> showhunk disasm dpaint
-
-
- 17C. bin/iconvert, bin/pragma2module
- ------------------------------------
-
- Ces 2 utilitaires sont pour les programmeurs E avancés seulement. Si vous
- ne vous sentez pas à la hauteur, sautez cette partie.
-
- [NOTE: comme l'utilitaire showmodule, les sources de ces utilitaires ont
- été enlevé de la distribution, parce que des personnes ont mal utilisé leur
- connaissance du format des modules .m. C'est PRIVÉE. Contactez moi d'abord
- si vous voulez faire quelquechose avec.]
-
- Iconvert convertie les définitions de constantes et de structures en assembleur,
- des fichiers '.i' en modules E. Pragma2module fait la même chose avec les
- fichiers de définition de bibliothèques pragma du compilateur SAS/C.
- Bien sûr, tous les includes de Commodore sont déja converties de cette façon,
- mais, disons que vous trouvez une chouette bibliothèque dans le domaine
- publique, vous aurez besoin de ces utilitaires.
-
- Comment faire :
-
- La plupart des bibliothèques sont fournies avec les définitions, mieux
- encore, avec les appels des fonctions, tout comme les constantes et les
- structures (OBJECT en E) que la bibliothèque utilise. Imaginons qu'elle
- s'appelle 'tools.library', vous devriez avoir :
-
- pragmas/tools_pragmas.h
- includes/tools.h
- includes/tools.i
-
- puis faites:
-
- 1> pragma2module tools_pragmas.h
-
- Maintenant, vous pouvez utiliser dans votre programme la bibliothèque
- 'tool.library'
-
- Exemple :
-
- MODULE 'tools'
-
- PROC main()
- IF (toolsbase:=Openlibrary('tools.library',37))=NIL THEN error()
-
- toolsfunc()
-
- ...etc.
-
- Convertissez 'tools.i' avec Iconvert en un autre 'tools.m' que vous
- mettrez dans emodules:libraries/, par exemple. Iconvert a besoin de
- l'assembleur A68k (domaine publique) pour faire le dur travail de
- compréhension de l'assembleur.
-
- 1> iconvert tools.i
-
- Regardez avec Showmodule ce qu'est devenu le fichier '.i'.
- Utilisez le dans votre programme avec :
-
- MODULE 'libraries/tools'
-
- DEF x:toolsobj, y=TOOLS_CONST
-
- Convertir avec Iconvert demande quelques notion d'assembleur, car
- Iconvert fait confiance au format du fichier '.i', comme les includes
- assembleur de Commodore. Environ 10% des fichier '.i' ont besoin d'être
- retouché à la main pour être 'convertissable'.
- Les définitions qu'Iconvert juge être correctes sont les suivants :
-
- <label> EQU <any_expression>
-
- STRUCTURE <sname>,0 ; if <>0, then <struct>_SIZEOF
- ULONG <sname>_<label>
- BPTR <sname>_<label>
- ; etc.
- LABEL <sname>_SIZEOF ; or "_SIZE"
-
- Pour avoir une idée, quel expression assembleur Iconvert peut reconnaitre,
- jetez un coup d'oeil dans les includes assembleur de Commodore et comparez les
- aux modules équivalents(par exemple Intuition.i).
-
-
- 17D. bin/ShowCache, bin/FlushCache
- ----------------------------------
-
- Le module cache du E est un espqce mémoire qu'il est possible de garder des
- modules .m entre 2 compilations. La première fois que vous utilisez un certain
- module, EC le chargera à partir du disque et le mettra dans le cache. Les fois
- suivantes, EC le retrouvera dans le cache et ne le rechargera pas. Si EC
- compile un module dont une ancienne version est dans le cache, celui-ci sera
- remplacé par la nouvelle version. Vous pouvez imaginer l'incroyable
- accellération des opérations, même pour les gens qui ont un disque dur et qui
- utilise beaucoup de modules et qui recompile souvent.
-
- Pour voir ce qui est à un moment donné dans le cache (et combien de mémoire
- il dépense :-), tapez :
-
- 1> ShowCache
-
- Un autre utilitaire, FlushCache, vous permet d'enlever des modules du cache.
- Des raisons à cela :
- - vous ne pouvez pas vous permettre d'utiliser tant de mémoire,
- - vous avez créé un nouveau .m avec un programme autre que EC, vous devez
- donc l'enlever 'à la main'.
- L'argument de FlushCache est la chaine de caractères qui apparait dans le nom
- du module. Aucun argument signifie tout enlever.
-
- Exemple :
-
- 1> FlushCache ; vide tout le cache
- 1> FlushCache intuition/ ; vide tout les modules en relation
- ; avec intuition
-
- Vous pouvez utiliser EC avec l'option 'IGNORECACHE/S' pour compiler sans le
- cache. Que le cache soit plein ou vide, EC chargera dans tous les cas à partir
- du disque, et ne mettra rien de nouveau dansle cache éxistant.
-
- Si 2 ECs essaie d'accéder au cache simultanément en multitache, le deuxième EC
- agira comme si l'option 'IGNORECACHE/S' était mis.
-
-
- 17E. rexx/ecompile.rexx
- -----------------------
- [Qui se garde les autres scripts Rexx ?]
-
- C'est un script rexx pour CygnusEd (tm), et vous permet de compiler des
- programmes E à partir de l'éditeur. Assignez seulement ce script à une
- touche de fonction de l'éditeur avec 'Install Dos/Arexx command ...'
- (Regardez dans le manuel de Ced, si vous n'êtes pas sûr).
- Maintenant écrivez votre programme, et pressez Fx si vous voulez compilez.
- Votre source sera sauvé si nécessaire, le compilateur sera chargé dans une
- fenêtre à part, et le programme est lancé sur cette même console. Quand votre
- programme est fait, pressez <Return> pour revenir dans l'éditeur (l'écran Ced
- est automatiquement mis en avant par le script). Si une érreur apparait
- pendant la compilation, le script laissera Ced sauter à la ligne de l'érreur,
- après que vous aillez pressez <Return>.
-
- Note : dans le script, les chemins d'accès au compilateur peuvent être trouvé.
- Vous aurez certainement à les changer. Le script copie EC en Ram:
- pour les systèmes avec un SYS: lent. Vous pouvez le désactiver si vous
- avez un disque dur.
-
-
- 17F. bin/o2m
- ------------
-
- Si vous avez des sources assembleur de grande taille que vous voulez utiliser,
- il serait préférable de les convertir 'à la main' en assembleur en ligne du E.
- o2m vous permet vous permet d'avoir votre macro-assembleur les assemblant out
- en un fichier .o, et o2, puis convertis ce fichier .o en un fichier .m
- utilisable en E.
-
- Exemple : Si vous avez un fixhier bla.o:
-
- 1> o2m bla
-
- donnera bla.m. Attention, le fichier .o doit obéir à certaines rêgles. Il doit
- consister en juste un seul code-hunk avec des définitions externes (XDEFs)
- pour chaque symbole que vous voulez définier à partir du E, et pas de XREFs.
- Votre source doit ressembler à ça :
-
- XDEF add__ii
-
- add__ii:
- move.l 4(a7),d0
- add.l 8(a7),d0
- rts
-
- Cet exemple montre un bout d'un code assembleur qui prend 2 arguments (d'ou les
- 2 "i" pour entier). Les arguments peuvent être trouvé dans la pile, où 4(a7)
- est le dernoier argument, 8(a7) le précédent etc.
-
- Showhunk vous affichera:
-
- hunk_unit:
- HUNK -1 hunk_name:
- hunk_code: 12 bytes
- hunk_ext
- add__ii = $0
-
- Ce type de fichier .o est facilement transformable en .m par o2m:
-
- /* Ce module contient 12 octets de code! */
-
- PROC add(a,b)
-
-
- Il y a 2 choses à noter:
- - si votre code utilise D3-D7/A4/A5, vous devriez le sauver ;
- - si un label n'a pas le "__" avec un "i" pour chaque fonction, celle-ci
- devient une fonction sans paramêtre. Ne vous inquiètez pas si le label
- définit des données, vous n'avez qu'a simplement prendre l'adresse de ce
- 'proc' avec {}, et l'utiliser comme pointeur sur vos données.
-
- Théoriquement, o2m peut être utiliser pour linker du code C aux programmes E,
- mais en pratique c'est souvent impossible. Si votre compilateur C vous permet
- de modifier ['tune'] le fichier .o un peu, ça doit marcher.
-
- Quelques problêmes sont:
- - les définitions de fonctions C, par exemple _printf() ;
- - les définitions de variables globales créées par le code startup du C ;
- Le code C définit "DOSBase" comme un XREF, alors que le code startup
- du E ;
- met à disposition cette valeur quelque part dans la pile,
- - les conventions d'appel/registre.
-
- Je me suis débrouillé pour linker un petite fonction C en E qui fait peu de
- chose, et l'appelle avec succès (ça a était fait avec MxonC++, dont le linker
- utilise aussi la convention __ii des paramêtres).
-
-
- 17G. bin/EYacc
- --------------
-
- C'est un portage du fameux Yacc d'unix, qui produit maintenant du code E au
- lieu du code C. C'est seulement une première version, n'en attendez pas trop
- de lui. Si vous n'avez aucune idée de ce que Yacc fait, lisez le texte à son
- propos, car je ne le ferait pas ici entièrement.
-
- Vous pouvez tout simplement écrire des sources .y comme d'habitude, seulement
- où des actions doivent écrite en C, vous l'écrivez maintenant en E.
- Reportez-vous à Src/Yacc/bcalc.y
-
- Exemple :
-
- 1> eyacc bcalc.y
-
- produit un fichier 'yyparse.e'
-
- 1> ec yyparse
-
- vous donnera un module qui ne contient que la fonction yyparse(). Le reste
- de 'comment interfacer avec Yacc' doit être analogue au C.
-
- [note: Je suis à la moitié de la traduction de Lex en E-Lex, mais pas encore
- fini.]
-
- Informations supplémentaires.
- E-Yacc est une modification du Yacc 1.8 de Berkeley, à l'origine par
- corbett@berkeley.edu. L'inclusion de cette version modifiée dans la
- distribution du E est tout à fait légale, comme l'auteur le certifie dans
- le README du BYacc1.8 original:
-
- " Berkeley Yacc is in the public domain. The data structures and algorithms
- used in Berkeley Yacc are all either taken from documents available to the
- general public or are inventions of the author. Anyone may freely distribute
- source or binary forms of Berkeley Yacc whether unchanged or modified.
- Distributers may charge whatever fees they can obtain for Berkeley Yacc.
- Programs generated by Berkeley Yacc may be distributed freely. "
-
- Traduction :
- Yacc de Berkeley est domaine public. Les structures de données et algorythmes
- utilisé dans Yacc de Berkeley sont tous tirés de documents disponibles au grand
- public ou sont l'invention de l'auteur. Chacun peut distribuer librement le
- source ou des formes binaires du Yacc de Berkeley qu'il soit inchangé ou
- modifié. Les distributeurs peuvent demander des droits qu'ils peuvent avoir
- sur Yacc de Berkeley. Les programmes générés par Yacc de Berkeley sont
- distribués gratuitement.
-
-
- 17H. bin/SrcGen
- ---------------
-
- [note: cet utilitaire n'a pas été mis à jour pour mieux travailler avec le
- système de module du E, il sortira toujours un source 'raw' (qui peut être
- facilement incorporé dans n'importe quel module). Si il y a assez de demande
- je ferai une mise à jour. Si vous voulez ajouter une chouette interface
- graphique à votre programme, jetez un coup d'oeil à modules/tools/EasyGUI.m,
- ou à de nouveau outils comme le prochain BGUI de Jan van den Baard, l'auteur
- de GadToolsBox.]
-
- ScrGen Générateur de source GadToolBox pour le E: version béta
-
- Vous aurez besoin de GadToolBox v2.0 ou plus, et avoir la gadtoolsbox.library
- qui vient avec, dans LIBS:. Maintenant, avec GTB, faites quelques exemples
- simples (juste une fenêtre avec quelques gadgets et menus etc.), sauvez le sous
- le nom "bla" (le nom de fichier sera "bla.gui"), et tapez:
-
- 1> SrcGen bla
- 1> EC bla
- 1> bla
-
- "bla.e" contient les routines pour ouvrir votre interface, tout comme les
- routines qui prennent les messages idcmp, erreurs etc., et un "main" vide
- qui attend juste une selection. Là vous pouvez mettre votre code. Voyez la
- ligne de commande de ScrGen pour savoir comment arrèter le génération de ces
- routines.
-
- C'est tout pour maintenant. Si vous avez des problêmes, vérifiez le source qui
- a été généré.
-
-
- 17I. bin/EBuild
- ---------------
-
- EBuild est un clone de "Make", et fonctionne tout comme lui. Build est un
- outils qui vous aide à recompiler des parties importantes d'une grande
- application après modification. Vous écrivez un fichier ".build" dans le
- répertoire qui contient les sources de votre projet. Le fichier contient les
- informations concernant les sources dépendant de quels autres, et quels
- actions doivent être faites si un module ou un éxécutable à besoin d'être
- recompilé. Build vérifie les dates des fichiers pour voir si le fichier a été
- modifié depuis la dernière compilation, et si le source utilise des modules
- qui ont été modifié, il les compilera en premier.
-
- La syntaxe est celle de la version unix. En général, "#" précède les lignes
- de commentaires, et:
-
- destination: dep1 dep2 ...
- action1
- action2
- ...
-
- Destination est le fichier qui en résulte, dans la plupart des cas, un
- éxéutable ou ou un module, mais peut^être autre chose aussi. Suivant les ":"
- vous écrivez tout les fichiers s'y rapportant, etr principalement son source,
- et d'autres modules. Les actions sur les lignes suivantes sont des commandes
- AmigaDOS normales, et ont besoin d'être précédées par au moins un espace ou
- une tabulation pour les différencier du fichiers destinations.
-
- bla: bla.e defs.m
- ec bla quiet
-
- Ce simple exemple reompilera simplement 'bla.e' si il était modifié ou si
- defs.m qu'il utilise l'a été.
-
- Si vous tapez 'build' sans argument, Build s'assurera que le premier fichier
- destination est mis à jour.
-
- TARGET,FROM/K,FORCE/S:
-
- Si vous mettez une destination ('TARGET'), de cette façon Build commencera
- avec une autre destination. FROM (de) vous permet de choisir un autre fichier
- autre que ".build", et FORCE refera tout ce qui est dans le fichier sans se
- soucier si c'était vraiment nécessaire.
-
- Exemple:
-
-
- # fichier Build test
-
- tout: bla burp
-
- defs.m: defs.e
- ec defs quiet
-
- truc: truc.e defs.m
- ec truc quiet
-
- machin: machin.e
- ec machin quiet
-
- nettoyer:
- delete defs.m truc machin
-
-
- Ce fichier Build concerne 2 programmes, 'truc' et 'machin'. Bla dépend du
- module defs.m. Une destination supplémentaire 'nettoyer' a été ajouté comme
- ça vous pouvez taper 'build nettoyer' pour effacer les fichiers créés.
-
- D'autres dépendance et actions peuvenet être facilement ajouté. Par exemple,
- si votre projet utilise un analyseur ('parser') généré par E-Yacc:
-
- yyparse.m: parser.y
- eyacc parser.y
- ec yyparse quiet
-
- Ou mettez-y du code macro-assembleur comme module:
-
- blerk.m: blerk.s
- a68k blerk.s
- o2m blerk
- copy blerk.m emodules:tools
- flushcache tools/blerk
-
- Une fois que vous connaitrez mieux Build, vous décrouvirez que vous pouvez
- aussi l'utiliser pour d'autre utilisation quel celle-là. Voyez le comme un
- outil de script intelligent.
-
- Si vous voulez trouver les détails de ce que peut faire Build, lisez la
- documentation de quelques 'make' d'unix, car Build devrait être compatible
- avec eux. Ce qu'il ne fait pas pour le moment, est:
-
- - régfir les dépendances de façon cyclique,
- - permettre le "\" à la fin de longue ligne,
- - les définitions de contantes.
-
-
-
- +---------------------------------------------------------------+
- | 18. Appendices |
- +---------------------------------------------------------------+
-
-
- 18A. La grammaire E
- -------------------
-
- syntaxe lex : expressions régulière
- syntaxe parse : propre adaptation ASF/SDF
-
- name = identificateur grammatical
- "name" = constante
- () = groupe
- | = ou
- e* = 0 ou plus que e
- e+ = 1 ou plus que e
- {e s}* = 0 ou plus que e séparaté par s
- {e s}+ = 1 ou plus que e séparaté par s
- [e] = e est optionel
- ; e = e est un commentaire :-)
-
-
- LEX
- ---
-
- whitespace = [ \t] ; et \n si le dernier token est [,+-*/]
- ; ou similaire
- n'importe quoi entre "/*" et "*/"
- de "->" à \n
- eol = [;\n]
-
- constant = [A-Z] ( [A-Z] [A-Za-z0-9_]* )?
- builtin = [A-Z] [a-z] [A-Za-z0-9_]*
- ident,objident = [a-z] [a-zA-Z0-9_]*
-
- num = [0-9]+ ; "-" est un token séparé
- $[0-9A-Fa-f]+
- %[01]+
- fnum = [0-9]*.[0-9]*
-
- stringconst = n'importe quoi entre ''
- charconst = n'importe quoi entre ""
-
-
- PARSE
- -----
-
- program = opts globalpart localpart
-
- globalpart = ( modulestat | defstat | objdecl | constdecl | raisedecl )*
- localpart = ( procdecl | constdecl )+
-
- modulestat = "MODULE" { conststring "," }+ eol
- defstat = "DEF" vardecllist eol
- objdecl = "OBJECT" ident [ "OF" ident ] eol
- ( vardecllist eol )+
- "ENDOBJECT" eol
- constdecl = "CONST" { ( constant "=" constexp ) "," }+ |
- "ENUM" { ( constant | constant "=" constexp ) "," }+ |
- "SET" { constant "," }+
- procdecl = [ "EXPORT" ] "PROC" ident "(" argdecllist ")" [ "HANDLE" ]
- ( "RETURN" { exp "," }* |
- eol defstat* stats
- [ "EXCEPT" eol stats ]
- "ENDPROC" { exp "," }* eol )
- raisedecl = "RAISE" { ( constant "IF" builtin "()" compop num ) "," }+
- opts = ( "OPT" { setting "," }+ )* ; dépendant de la machine
-
- vardecllist = { vardecl "," }+
- vardecl = ident [ "=" num ]
- [ ":" ( "LONG" | "REAL" | "PTR" "TO" ptrtype ) ] |
- ident ":" objtype |
- ident "[" num "]" ":"
- ( "ARRAY" |
- "ARRAY" "OF" ptrtype |
- "STRING" |
- "LIST" )
- argdecllist = { argdecl "," }+
- argdecl = ident [ "=" defaultarg ]
- [ ":" ( "LONG" | "REAL" | "PTR" "TO" ptrtype ) ]
- ptrtype = objtype | simpletype
- simpletype = CHAR | INT | LONG
- objtype = ident
-
- stats = ( ( onelinestat | multlinestat ) eol )*
- onelinestat = exp |
- lval ":=" exp |
- { var "," }+ ":=" exp |
- "IF" exp "THEN" onelinestat "ELSE" onelinestat |
- "FOR" var ":=" exp "TO" exp [ "STEP" num ]
- "DO" onelinestat |
- "WHILE" exp "DO" onelinestat |
- "RETURN" { exp "," }* |
- "JUMP" ident |
- ( "INC" | "DEC" ) var | ; presque obsolète
- asm_mnemonic { operand "," }* | ; dépendant de la machine
- "INCBIN" stringconst | ; support asm
- simpletype { num "," }+ |
- "VOID" exp ; obsolète
- multlinestat = "IF" exp eol stats
- [ ( "ELSEIF" exp eol stats )* ]
- [ "ELSE" eol stats ]
- "ENDIF" |
- "FOR" var ":=" exp "TO" exp [ "STEP" num ] eol
- stats "ENDPROC" |
- "WHILE" exp eol stats "ENDWHILE" |
- "REPEAT" eol stats "UNTIL" exp |
- "SELECT" var eol
- ( "CASE" exp eol stats )+
- [ "DEFAULT" eol stats ]
- "ENDSELECT" |
- "LOOP" eol stats "ENDLOOP"
-
- explist = { exp "," }+
- exp = [ "-" ] { item binop }+ |
- exp "BUT" exp
- item = num | fnum | lval | stringconst | charconst |
- "SIZEOF" objident |
- "IF" exp "THEN" exp "ELSE" exp |
- "[" explist "]" [ ":" ptrtype ] |
- ( builtin | ident ) "(" explist ")" |
- var ":=" exp |
- "{" ident "}" |
- "`" exp |
- binop = mathop | compop | logop
- mathop = "+" | "-" | "*" | "/"
- compop = "=" | "<>" | ">" | "<" | ">=" | "<="
- logop = "AND" | "OR"
- constexp = [ "-" ] { num ( "+" | "-" | "*" | "/" ) }+
- lval = var [ "[" [ exp ] "]" ] [ "." ident ] [ "++" | "--" ] |
- "^" var [ "++" | "--" ] |
- var = ident
- defaultarg = num
-
-
- 18B. Tutorial
- -------------
-
- Note : le tutorial original de l'Amiga E v2.1b a été supprimé, car il n'était
- pas très utile, à mon humble opinion. A la place, Jason Hulance a écrit un
- tutorial extensif sur le E dans lequel vous devrez absolument jeter un coup
- d'oeil.
-
-
- 18C. Comparaison du E avec C/C++/Pascal/Ada/Lisp etc.
- -----------------------------------------------------
-
- [des petits plus ont été aoujoté ici]
-
- Dans les 2 premières colonnes, je compare le E avec le C/C++ ANSI. La
- troisième colonne est réservée à un autre langage. J'y mettrais souvent le
- Pascal, mais quand une des caractèristiques y apparait, j'en mettais un
- autre (par exemple, le LISP et les expressions cotées, ADA et les exceptions).
-
- Note : ne prenez pas ces tables à la lettre. J'ai essayé de marquer les
- équivalences syntaxiques, et les propriétés sémantiques du mieux possible,
- mais les différents langages possèdent leurs propre évaluation.
-
- Si vous trouvez des erreurs dans la translation, faites le moi savoir, s'il
- vous plait (en particulier pour le Pascal, les connaisances sont un peu
- 'vieille')
-
- signification des signes :
-
- - = cette caractèristique n'éxiste pas dans ce langage.
- ? = l'auteur n'est pas sur de la translation.
- ... = la caractèristique doit être possible, mais la translation n'est pas
- directe pour être intéressante.
- x,y,z = identificateurs arbitraires
- e,f,g = expressions arbitraires
- s,t,u = déclarations arbitraires
- i,j,k = entiers arbitraires
- etc.
-
-
- -----------------------------------------------------------------------
- STRUCTURE/DÉCLARARTION
-
- E C/C++ Pascal
- ----------------------- ----------------------- -----------------------
- PROC x() int x() { FUNCTION x:INTEGER;
- PROC x(y,z) int x(y,z) { FUNCTION x(y,z:INTEGER):INTEGER;
- PROC x(y=1) int x(y=1) { -
- ENDPROC return 0; }; x:=0; END;
- ENDPROC e return e; }; x:=e; END;
- RETURN e return e; ?
-
- IF e if(e) { IF e THEN BEGIN
- ELSEIF e } else if(e) { END ELSE IF e THEN BEGIN
- ELSE } else { END ELSE BEGIN
- ENDIF }; END;
- IF e THEN s if(e) s; IF e THEN s;
- IF e THEN s ELSE t if(e) s else t; IF e THEN s ELSE t;
-
- FOR x:=e TO f - (1) FOR x:=e TO f DO BEGIN
- FOR x:=e TO f STEP i - - (2)
- EXIT e if(e) break; -
- ENDFOR - END;
- FOR x:=e TO f DO s - FOR x:=e TO f DO s;
-
- WHILE e while(e) { WHILE e DO BEGIN
- EXIT e if(e) break; -
- ENDWHILE }; END;
- WHILE e DO s while(e) s; WHILE e DO s;
-
- s; WHILE e for(s;e;u) { s; WHILE e DO BEGIN
- t; u t; t; u
- ENDWHILE }; END;
-
- REPEAT do { REPEAT
- UNTIL e } while(!e); UNTIL e;
-
- LOOP for(;;) { WHILE TRUE DO BEGIN (?)
- ENDLOOP }; END;
-
- SELECT x switch(x) { CASE x OF
- SELECT x OF y switch(x) { CASE x OF
- CASE 1; s... case 1: s...; break 1: BEGIN s... END
- CASE a+1 - -
- CASE 1,2,3 case 1: case 2: case3: 1,2,3:
- CASE "a".."z" - -
- ENDSELECT }; END
-
- INC x x++; x:=x+1; (INC())
- DEC x x--; x:=x-1; (DEC())
- JUMP lab goto lab; GOTO lab;
- x:=e x=e; x:=e;
-
- /* */ /* */ { }
- -> // -
-
- (1) voir WHILE; C n'a pas de FOR, "for" en C est une autre façon d'utiliser
- "while"
- (2) uniquement STEP -1 pour DOWNTO
-
-
- -----------------------------------------------------------------------
- VALEURS
-
- E C/C++ Pascal
- ----------------------- ----------------------- -----------------------
- 1 1 1
- 1.0 1.0 1.0
- $1 0x1 ?
- %1 ? ?
- "a" 'a' chr(97) (?)
- 'blabla' "blabla" 'blabla'
- [1,2,3] - (1) -
- [1,2,3]:INT - -
-
- (1) dans la traduction de E en C, vous pouvez les simuler par :
-
- myfunc([1,2,3])
-
- devient
-
- int dummy [] = {1,2,3};
- myfunc(dummy);
-
-
- -----------------------------------------------------------------------
- OPERATEURS
-
- E C/C++ Pascal
- ----------------------- ----------------------- -----------------------
- + - * / + - * / + - * DIV
- = <> > < >= <= == != > < >= <= = <> > < >= <=
- AND OR (log) && || and or
- AND OR (bit) & | ?
- SIZEOF x sizeof(x) -
- `e - - (1)
- ^x (4) *x ...
- {x} &x ...
- x++ x++ -
- x-- --x -
- -x -x -x
- IF e THEN f ELSE g e ? f : g -
- x.y x->y x.y x^.y x.y
- a:=x.y; a.z x->y->z x.y.z x^.y^.z x.y.z
- x:=e x=e -
- e BUT f (e,f) -
- x[] x[0] *x (2) x[0]
- x[1] x[1] x[1]
- x[1] (3) &x[1] ?
- x[1].y x[1]->y x[1]^.y
- x[]++ *x++ -
- x[1].y++ *(x+1)++ -
- x::y.a ((y *)x)->a -
- x.y::z.a ((z *)x->y)->a -
-
- (1) voir EXPRESSIONS COTÉES
- (2) de même pour d'autres, les équivalences entre *(x+e) et x[e] sont faites.
- (3) si ARRAY OF <objet>
- (4) SEULEMENT pour donner en référence. sinon: "[]"
-
-
- -----------------------------------------------------------------------
- CONSTANTES/TYPES
-
- E C/C++ Pascal
- ----------------------- ----------------------- -----------------------
- CONST X=1 #define X 1 CONST X=1;
- const int X=1;
- ENUM X,Y,Z #define X 0 (etc.) TYPE x=(X,Y,Z);
- enum x{X,Y,Z};
- SET X,Y,Z - TYPE x=SET OF (X,Y,Z);
-
- DEF VAR
- x int x; (or: long x;) x:INTEGER;
- x:LONG int x; x:INTEGER;
- x:PTR TO y struct y* x; x:^y;
- x:y struct y x; x:y;
- x[10]:ARRAY OF y struct y x[10]; x:ARRAY [0..9] OF y;
- x[10]:STRING - (1) x:STRING[10]; (2)
- x[10]:LIST - (1) - (1)
-
- x:REG register int x;
-
- OBJECT x struct x { (3) TYPE x = RECORD
- y:CHAR,z:INT char y; short z; y:CHAR; z:INTEGER;
- ENDOBJECT }; END;
-
- (1) dans la traduction de E en C, simulez avec un tableau de char/int
- respectivement, et faites votre propre vérification, etc.
- (2) n'est pas dans le Pascal standard, mais possible dans tous les dialectes.
- (3) ou de classe publique (public class) bien sûr...
-
-
- -----------------------------------------------------------------------
- EXPRESSIONS COTÉES
-
- E LISP MIRANDA
- ----------------------- --------------------------- -------------------
- `e (QUOTE e) 'e (3)
- (LAMBDA () e) (1)
- `x+y '(+ x y)
- Eval(`e) (EVAL `e)
- ForAll(v,l,`e) - (2)
- MapList(v,l,l,`e) (MAPCAR (LAMBDA (V) E) L) map (\v->e) l
-
- exemple:
-
- E: MapList({x},[1,2,3,4],a,`x*x)
- MIRANDA: map (\x->x*x) [1,2,3,4]
- LISP: (MAPCAR (LAMBDA (X) (* X X) `(1 2 3 4))
-
- (1) de vraies cotes `, mais des fois utilisés, où en LIST, la fonction LAMBDA
- aurait été utilisé, comme MapList().
- (2) même pas en Prolog, voir d'autres langages logiques.
- (3) on sera plutôt flemmard ici
-
-
- -----------------------------------------------------------------------
- UNIFICATION AND CELLULES LISP
-
- E LISP PROLOG
- ----------------------- ----------------------- -----------------------
- <1|2> (1 . 2) [1|2]
- <1,2,3> (1 2 3) [1,2,3]
- <1,2|3> (1 2 . 3) [1,2|3]
-
- E HASKELL PROLOG
- ----------------------- ----------------------- -----------------------
- e <=> <x|y> (x:y) = e e = [X|Y]
- e <=> <1,2,x> [1,2,x] = e e = [1,2,X]
- e <=> [1,x] - -
-
-
- -----------------------------------------------------------------------
- EXCEPTIONS
-
- E C++ ADA
- ----------------------- ----------------------- -----------------------
- PROC x() HANDLE int x() { try { function x is begin
- EXCEPT } catch (exc) { (1) exception
- EXCEPT DO - -
- ENDPROC }}; end x;
-
- Raise(e) throw e; raise e;
- Throw(e,f) ? -
- ReThrow() throw e; raise e;
- RAISE "MEM" IF New()=0 - - (2)
-
-
- (1) catch gère un seule exception, c'est différent des gestionnaires
- d'exception généraux comme utilisé en E.
- (2) le système ne lève que uelques exceptions, mais je ne suis pas sûr si
- des levées d'exceptions automatiques peuvent être définies en Ada.
-
-
- -----------------------------------------------------------------------
- PROGRAMMATION ORIENTÉ OBJET
-
- E C++
- ------------------------------- -----------------------
- OBJECT x class x {
- OBJECT x OF y class x : y {
- self.i this->i
- PROC a OF x IS self.i virtual int x::a() { return i; }
- - int x::a() { return i; }
- PROC a OF x IS EMPTY virtual int x::a() =0
- PUBLIC public:
- a.method(1) a->method(1)
-
- [voir aussi la prochaine partie sous NEW]
-
- -----------------------------------------------------------------------
- FONCTIONS PRÉDÉFINIES (BUILT-IN)
- (seulement quelques uns sont là, comme exemple)
-
- E C/C++ Pascal
- ----------------------- ----------------------- -----------------------
- WriteF(fs,...) printf(fs,...); WriteLn(a,b,...);
- cout << a << b ... ;
-
- ReadStr(f,s) scanf(fs,...) ReadLn(s)
- Val(s,n) Val()
- cin >> s;
-
- StrCopy(s,s,n) (1) strcpy(s,s) s:=s; (2)
-
- Mod(e,e) e%e e MOD e
- Shl(e,n) e<<n Shl()
- Long(e) - -
-
- p:=New(e) p=malloc(e); New(p);
- NEW p p=new type;
- NEW p.constr() p=new constr() -
- NEW [e,f,g] - -
- Dispose(p) free(p); Dispose(p);
- delete p;
-
- (1) en traduisant du C, fait attention à transformer les tableaux de char en
- chaines (string).
- (2) ch'sait pas quelle fonction est nécessaire dans le cas d'un pointeur.
-